326 lines
10 KiB
Java
326 lines
10 KiB
Java
/*
|
|
* 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();
|
|
}
|
|
}
|
|
}
|