| /* |
| * 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.FlaggedApi; |
| import android.annotation.IntDef; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| 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.security.Flags; |
| import android.service.oemlock.OemLockManager; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| |
| /** |
| * Interface to the persistent data partition. Provides access to information about the state |
| * of factory reset protection. |
| */ |
| @FlaggedApi(Flags.FLAG_FRP_ENFORCEMENT) |
| @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. |
| * |
| * @hide |
| */ |
| @SystemApi |
| public static final int FLASH_LOCK_UNKNOWN = -1; |
| /** |
| * Indicates that the device's bootloader is UNLOCKED. |
| * |
| * @hide |
| */ |
| @SystemApi |
| public static final int FLASH_LOCK_UNLOCKED = 0; |
| /** |
| * Indicates that the device's bootloader is LOCKED. |
| * |
| * @hide |
| */ |
| @SystemApi |
| public static final int FLASH_LOCK_LOCKED = 1; |
| |
| /** |
| * @removed mistakenly exposed previously |
| * |
| * @hide |
| */ |
| @SystemApi |
| @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 |
| * |
| * @hide |
| */ |
| @SystemApi |
| @SuppressLint("RequiresPermission") |
| public int write(@Nullable byte[] data) { |
| try { |
| return sService.write(data); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Returns the data block stored on the persistent partition. |
| * |
| * @hide |
| */ |
| @SystemApi |
| @SuppressLint("RequiresPermission") |
| public @Nullable 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. |
| * |
| * @hide |
| */ |
| @SystemApi |
| @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. |
| * |
| * @hide |
| */ |
| @SystemApi |
| @SuppressLint("RequiresPermission") |
| 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. |
| * |
| * @hide |
| */ |
| @SystemApi |
| @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. |
| * |
| * @hide |
| */ |
| @SystemApi |
| @Deprecated |
| @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. |
| * |
| * @hide |
| */ |
| @SystemApi |
| @Deprecated |
| @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. |
| * |
| * @hide |
| */ |
| @SystemApi |
| @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(); |
| } |
| } |
| |
| /** |
| * Returns the package name which can access the persistent data partition. |
| * |
| * @hide |
| */ |
| @SystemApi |
| @NonNull |
| @RequiresPermission(android.Manifest.permission.ACCESS_PDB_STATE) |
| public String getPersistentDataPackageName() { |
| try { |
| return sService.getPersistentDataPackageName(); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Returns true if FactoryResetProtection (FRP) is active, meaning the device rebooted and has |
| * not been able to deactivate FRP because the deactivation secrets were wiped by an untrusted |
| * factory reset. |
| */ |
| @FlaggedApi(Flags.FLAG_FRP_ENFORCEMENT) |
| public boolean isFactoryResetProtectionActive() { |
| try { |
| return sService.isFactoryResetProtectionActive(); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Attempt to deactivate FRP with the provided secret. If the provided secret matches the |
| * stored FRP secret, FRP is deactivated and the method returns true. Otherwise, FRP state |
| * remains unchanged and the method returns false. |
| * |
| * @hide |
| */ |
| @FlaggedApi(Flags.FLAG_FRP_ENFORCEMENT) |
| @SystemApi |
| @RequiresPermission(android.Manifest.permission.CONFIGURE_FACTORY_RESET_PROTECTION) |
| public boolean deactivateFactoryResetProtection(@NonNull byte[] secret) { |
| try { |
| return sService.deactivateFactoryResetProtection(secret); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| |
| /** |
| * Store the provided FRP secret as the secret to be used for future FRP deactivation. The |
| * secret must be 32 bytes in length. Setting the all-zeros "default" value disables the FRP |
| * feature entirely. |
| * |
| * To ensure that the device doesn't end up in a bad state if a crash occurs, this method |
| * should be used in a three-step process: |
| * |
| * 1. Generate a new secret and securely store any necessary copies (e.g. by encrypting them |
| * and calling #write with a new data block that contains both the old encrypted secret |
| * copies and the new ones). |
| * 2. Call this method to set the new FRP secret. This will also write the copy used during |
| * normal boot. |
| * 3. Delete any old FRP secret copies (e.g. by calling #write with a new data block that |
| * contains only the new encrypted secret copies). |
| * |
| * Note that this method does nothing if FRP is currently active. |
| * |
| * This method does not require any permission, but can be called only by the |
| * PersistentDataBlockService's authorized caller UID. |
| * |
| * Returns true if the new secret was successfully written. Returns false if FRP is currently |
| * active. |
| * |
| * @hide |
| */ |
| @FlaggedApi(Flags.FLAG_FRP_ENFORCEMENT) |
| @SystemApi |
| @SuppressLint("RequiresPermission") |
| public boolean setFactoryResetProtectionSecret(@NonNull byte[] secret) { |
| try { |
| return sService.setFactoryResetProtectionSecret(secret); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| } |
| } |