content: /*
   * Copyright (C) 2014 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package android.service.persistentdata;
  
  import android.annotation.IntDef;
  import android.annotation.RequiresPermission;
  import android.annotation.SuppressLint;
  import android.annotation.SystemApi;
  import android.annotation.SystemService;
  import android.content.Context;
  import android.os.RemoteException;
  import android.service.oemlock.OemLockManager;
  
  import java.lang.annotation.Retention;
  import java.lang.annotation.RetentionPolicy;
  
  /**
   * Interface for reading and writing data blocks to a persistent partition.
   *
   * Allows writing one block at a time. Namely, each time
   * {@link PersistentDataBlockManager#write(byte[])}
   * is called, it will overwite the data that was previously written on the block.
   *
   * Clients can query the size of the currently written block via
   * {@link PersistentDataBlockManager#getDataBlockSize()}.
   *
   * Clients can query the maximum size for a block via
   * {@link PersistentDataBlockManager#getMaximumDataBlockSize()}
   *
   * Clients can read the currently written block by invoking
   * {@link PersistentDataBlockManager#read()}.
   *
   * @hide
   */
  @SystemApi
  @SystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE)
  public class PersistentDataBlockManager {
      private static final String TAG = PersistentDataBlockManager.class.getSimpleName();
      private IPersistentDataBlockService sService;
  
      /**
       * Indicates that the device's bootloader lock state is UNKNOWN.
       */
      public static final int FLASH_LOCK_UNKNOWN = -1;
      /**
       * Indicates that the device's bootloader is UNLOCKED.
       */
      public static final int FLASH_LOCK_UNLOCKED = 0;
      /**
       * Indicates that the device's bootloader is LOCKED.
       */
      public static final int FLASH_LOCK_LOCKED = 1;
  
      @IntDef(prefix = { "FLASH_LOCK_" }, value = {
              FLASH_LOCK_UNKNOWN,
              FLASH_LOCK_LOCKED,
              FLASH_LOCK_UNLOCKED,
      })
      @Retention(RetentionPolicy.SOURCE)
      public @interface FlashLockState {}
  
      /** @hide */
      public PersistentDataBlockManager(IPersistentDataBlockService service) {
          sService = service;
      }
  
      /**
       * Writes {@code data} to the persistent partition. Previously written data
       * will be overwritten. This data will persist across factory resets.
       *
       * Returns the number of bytes written or -1 on error. If the block is too big
       * to fit on the partition, returns -MAX_BLOCK_SIZE.
       *
       * {@link #wipe} will block any further {@link #write} operation until reboot,
       * in which case -1 will be returned.
       *
       * @param data the data to write
       */
      @SuppressLint("Doclava125")
      public int write(byte[] data) {
          try {
              return sService.write(data);
          } catch (RemoteException e) {
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Returns the data block stored on the persistent partition.
       */
      @SuppressLint("Doclava125")
      public byte[] read() {
          try {
              return sService.read();
          } catch (RemoteException e) {
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Retrieves the size of the block currently written to the persistent partition.
       *
       * Return -1 on error.
       */
      @RequiresPermission(android.Manifest.permission.ACCESS_PDB_STATE)
      public int getDataBlockSize() {
          try {
              return sService.getDataBlockSize();
          } catch (RemoteException e) {
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Retrieves the maximum size allowed for a data block.
       *
       * Returns -1 on error.
       */
      @SuppressLint("Doclava125")
      public long getMaximumDataBlockSize() {
          try {
              return sService.getMaximumDataBlockSize();
          } catch (RemoteException e) {
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Zeroes the previously written block in its entirety. Calling this method
       * will erase all data written to the persistent data partition.
       * It will also prevent any further {@link #write} operation until reboot,
       * in order to prevent a potential race condition. See b/30352311.
       */
      @RequiresPermission(android.Manifest.permission.OEM_UNLOCK_STATE)
      public void wipe() {
          try {
              sService.wipe();
          } catch (RemoteException e) {
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Writes a byte enabling or disabling the ability to "OEM unlock" the device.
       *
       * @deprecated use {@link OemLockManager#setOemUnlockAllowedByUser(boolean)} instead.
       */
      @RequiresPermission(android.Manifest.permission.OEM_UNLOCK_STATE)
      public void setOemUnlockEnabled(boolean enabled) {
          try {
              sService.setOemUnlockEnabled(enabled);
          } catch (RemoteException e) {
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Returns whether or not "OEM unlock" is enabled or disabled on this device.
       *
       * @deprecated use {@link OemLockManager#isOemUnlockAllowedByUser()} instead.
       */
      @RequiresPermission(anyOf = {
              android.Manifest.permission.READ_OEM_UNLOCK_STATE,
              android.Manifest.permission.OEM_UNLOCK_STATE
      })
      public boolean getOemUnlockEnabled() {
          try {
              return sService.getOemUnlockEnabled();
          } catch (RemoteException e) {
              throw e.rethrowFromSystemServer();
          }
      }
  
      /**
       * Retrieves available information about this device's flash lock state.
       *
       * @return {@link #FLASH_LOCK_LOCKED} if device bootloader is locked,
       * {@link #FLASH_LOCK_UNLOCKED} if device bootloader is unlocked, or {@link #FLASH_LOCK_UNKNOWN}
       * if this information cannot be ascertained on this device.
       */
      @RequiresPermission(anyOf = {
              android.Manifest.permission.READ_OEM_UNLOCK_STATE,
              android.Manifest.permission.OEM_UNLOCK_STATE
      })
      @FlashLockState
      public int getFlashLockState() {
          try {
              return sService.getFlashLockState();
          } catch (RemoteException e) {
              throw e.rethrowFromSystemServer();
          }
      }
  }
  