Add implementation alternatives for OemLockManager.
The OEM lock can be implemented with the persistent data block or the
OemLock HAL.
Test: gts-tradefed run gts -m GtsOemLockServiceTestCases -t com.google.android.oemlock.gts.OemLockServiceTest
Bug: 34766843
Change-Id: I16b31785d9af58212a050a299ef024be3139f0c6
diff --git a/core/java/android/service/oemlock/IOemLockService.aidl b/core/java/android/service/oemlock/IOemLockService.aidl
index 2c606f9..682e7ee 100644
--- a/core/java/android/service/oemlock/IOemLockService.aidl
+++ b/core/java/android/service/oemlock/IOemLockService.aidl
@@ -27,4 +27,8 @@
void setOemUnlockAllowedByUser(boolean allowed);
boolean isOemUnlockAllowedByUser();
+
+ boolean canUserAllowOemUnlock();
+ boolean isOemUnlockAllowed();
+ boolean isDeviceOemUnlocked();
}
diff --git a/core/java/android/service/oemlock/OemLockManager.java b/core/java/android/service/oemlock/OemLockManager.java
index c4fbe5e..9e69362 100644
--- a/core/java/android/service/oemlock/OemLockManager.java
+++ b/core/java/android/service/oemlock/OemLockManager.java
@@ -82,7 +82,8 @@
*
* All actors involved must agree for OEM unlock to be possible.
*
- * @param unlocked Whether the device should be made OEM unlocked.
+ * @param allowed Whether the device should be allowed to be unlocked.
+ * @throws SecurityException if the user is not allowed to unlock the device.
*
* @see #isOemUnlockAllowedByUser()
*/
@@ -107,4 +108,48 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Returns whether all parties other than the user allow OEM unlock meaning the user can
+ * directly control whether or not the device can be OEM unlocked.
+ *
+ * If this is true, {@link #isOemUnlockAllowedByUser} is the same as {@link #isOemUnlockAllowed}
+ *
+ * @return Whether the user can directly control whether the device can be OEM unlocked.
+ *
+ * @hide
+ */
+ public boolean canUserAllowOemUnlock() {
+ try {
+ return mService.canUserAllowOemUnlock();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @return Whether the bootloader is able to OEM unlock the device.
+ *
+ * @hide
+ */
+ public boolean isOemUnlockAllowed() {
+ try {
+ return mService.isOemUnlockAllowed();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @return Whether the device has been OEM unlocked by the bootloader.
+ *
+ * @hide
+ */
+ public boolean isDeviceOemUnlocked() {
+ try {
+ return mService.isOemUnlockAllowed();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 7f07f03..22d7541 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -229,6 +229,7 @@
<permission name="android.permission.MANAGE_FINGERPRINT"/>
<permission name="android.permission.MANAGE_USB"/>
<permission name="android.permission.MANAGE_USERS"/>
+ <permission name="android.permission.MANAGE_USER_OEM_UNLOCK_STATE" />
<permission name="android.permission.MASTER_CLEAR"/>
<permission name="android.permission.MODIFY_PHONE_STATE"/>
<permission name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
diff --git a/services/core/Android.mk b/services/core/Android.mk
index f896478..94a3e0a 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -30,6 +30,7 @@
tzdata_update2 \
android.hidl.base-V1.0-java-static \
android.hardware.biometrics.fingerprint-V2.1-java-static \
+ android.hardware.oemlock-V1.0-java-static \
android.hardware.vibrator-V1.0-java-constants \
ifneq ($(INCREMENTAL_BUILDS),)
diff --git a/services/core/java/com/android/server/OemLockService.java b/services/core/java/com/android/server/OemLockService.java
deleted file mode 100644
index 03f82a8..0000000
--- a/services/core/java/com/android/server/OemLockService.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2017 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 com.android.server;
-
-import android.Manifest;
-import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.content.Context;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.service.oemlock.IOemLockService;
-import android.service.persistentdata.PersistentDataBlockManager;
-
-/**
- * Service for managing the OEM lock state of the device.
- *
- * The current implementation is a wrapper around the previous implementation of OEM lock.
- * - the DISALLOW_OEM_UNLOCK user restriction was set if the carrier disallowed unlock
- * - the user allows unlock in settings which calls PDBM.setOemUnlockEnabled()
- */
-public class OemLockService extends SystemService {
- private Context mContext;
-
- public OemLockService(Context context) {
- super(context);
- mContext = context;
- }
-
- @Override
- public void onStart() {
- publishBinderService(Context.OEM_LOCK_SERVICE, mService);
- }
-
- private boolean doIsOemUnlockAllowedByCarrier() {
- return !UserManager.get(mContext).hasUserRestriction(UserManager.DISALLOW_OEM_UNLOCK);
- }
-
- private boolean doIsOemUnlockAllowedByUser() {
- final PersistentDataBlockManager pdbm = (PersistentDataBlockManager)
- mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
-
- final long token = Binder.clearCallingIdentity();
- try {
- return pdbm.getOemUnlockEnabled();
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- /**
- * Implements the binder interface for the service.
- */
- private final IBinder mService = new IOemLockService.Stub() {
- @Override
- public void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
- enforceManageCarrierOemUnlockPermission();
- enforceUserIsAdmin();
-
- // Note: this implementation does not require a signature
-
- // Continue using user restriction for backwards compatibility
- final UserHandle userHandle = UserHandle.of(UserHandle.getCallingUserId());
- final long token = Binder.clearCallingIdentity();
- try {
- UserManager.get(mContext)
- .setUserRestriction(UserManager.DISALLOW_OEM_UNLOCK, !allowed, userHandle);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public boolean isOemUnlockAllowedByCarrier() {
- enforceManageCarrierOemUnlockPermission();
- return doIsOemUnlockAllowedByCarrier();
- }
-
- @Override
- public void setOemUnlockAllowedByUser(boolean allowedByUser) {
- if (ActivityManager.isUserAMonkey()) {
- // Prevent a monkey from changing this
- return;
- }
-
- enforceManageUserOemUnlockPermission();
- enforceUserIsAdmin();
-
- final PersistentDataBlockManager pdbm = (PersistentDataBlockManager)
- mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
-
- final long token = Binder.clearCallingIdentity();
- try {
- // The method name is misleading as it really just means whether or not the device
- // can be unlocked but doesn't actually do any unlocking.
- pdbm.setOemUnlockEnabled(allowedByUser);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
- public boolean isOemUnlockAllowedByUser() {
- enforceManageUserOemUnlockPermission();
- return doIsOemUnlockAllowedByUser();
- }
- };
-
- private void enforceManageCarrierOemUnlockPermission() {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE,
- "Can't manage OEM unlock allowed by carrier");
- }
-
- private void enforceManageUserOemUnlockPermission() {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE,
- "Can't manage OEM unlock allowed by user");
- }
-
- private void enforceUserIsAdmin() {
- final int userId = UserHandle.getCallingUserId();
- final long token = Binder.clearCallingIdentity();
- try {
- if (!UserManager.get(mContext).isUserAdmin(userId)) {
- throw new SecurityException("Must be an admin user");
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-}
diff --git a/services/core/java/com/android/server/oemlock/OemLock.java b/services/core/java/com/android/server/oemlock/OemLock.java
new file mode 100644
index 0000000..ee70c29
--- /dev/null
+++ b/services/core/java/com/android/server/oemlock/OemLock.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 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 com.android.server.oemlock;
+
+import android.annotation.Nullable;
+
+abstract class OemLock {
+ abstract void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature);
+ abstract boolean isOemUnlockAllowedByCarrier();
+
+ abstract void setOemUnlockAllowedByDevice(boolean allowedByDevice);
+ abstract boolean isOemUnlockAllowedByDevice();
+}
diff --git a/services/core/java/com/android/server/oemlock/OemLockService.java b/services/core/java/com/android/server/oemlock/OemLockService.java
new file mode 100644
index 0000000..5e19b13
--- /dev/null
+++ b/services/core/java/com/android/server/oemlock/OemLockService.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2017 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 com.android.server.oemlock;
+
+import android.Manifest;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.oemlock.V1_0.IOemLock;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.os.UserManagerInternal;
+import android.os.UserManagerInternal.UserRestrictionsListener;
+import android.service.oemlock.IOemLockService;
+import android.util.Slog;
+
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+import com.android.server.pm.UserRestrictionsUtils;
+
+/**
+ * Service for managing the OEM lock state of the device.
+ *
+ * The OemLock HAL will be used if it is available, otherwise the persistent data block will be
+ * used.
+ */
+public class OemLockService extends SystemService {
+ private static final String TAG = "OemLock";
+
+ private static final String FLASH_LOCK_PROP = "ro.boot.flash.locked";
+ private static final String FLASH_LOCK_UNLOCKED = "0";
+
+ private Context mContext;
+ private OemLock mOemLock;
+
+ public static boolean isHalPresent() {
+ return VendorLock.getOemLockHalService() != null;
+ }
+
+ /** Select the OEM lock implementation */
+ private static OemLock getOemLock(Context context) {
+ final IOemLock oemLockHal = VendorLock.getOemLockHalService();
+ if (oemLockHal != null) {
+ Slog.i(TAG, "Using vendor lock via the HAL");
+ return new VendorLock(context, oemLockHal);
+ } else {
+ Slog.i(TAG, "Using persistent data block based lock");
+ return new PersistentDataBlockLock(context);
+ }
+ }
+
+ public OemLockService(Context context) {
+ this(context, getOemLock(context));
+ }
+
+ OemLockService(Context context, OemLock oemLock) {
+ super(context);
+ mContext = context;
+ mOemLock = oemLock;
+
+ LocalServices.getService(UserManagerInternal.class)
+ .addUserRestrictionsListener(mUserRestrictionsListener);
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.OEM_LOCK_SERVICE, mService);
+ }
+
+ private final UserRestrictionsListener mUserRestrictionsListener =
+ new UserRestrictionsListener() {
+ @Override
+ public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
+ Bundle prevRestrictions) {
+ // The admin can prevent OEM unlock with the DISALLOW_FACTORY_RESET user restriction
+ if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
+ UserManager.DISALLOW_FACTORY_RESET)) {
+ final boolean unlockAllowedByAdmin =
+ !newRestrictions.getBoolean(UserManager.DISALLOW_FACTORY_RESET);
+ if (!unlockAllowedByAdmin) {
+ mOemLock.setOemUnlockAllowedByDevice(false);
+ }
+ }
+ }
+ };
+
+ /**
+ * Implements the binder interface for the service.
+ *
+ * This checks for the relevant permissions before forwarding the call to the OEM lock
+ * implementation being used on this device.
+ */
+ private final IBinder mService = new IOemLockService.Stub() {
+ @Override
+ public void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
+ enforceManageCarrierOemUnlockPermission();
+ enforceUserIsAdmin();
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mOemLock.setOemUnlockAllowedByCarrier(allowed, signature);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public boolean isOemUnlockAllowedByCarrier() {
+ enforceManageCarrierOemUnlockPermission();
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return mOemLock.isOemUnlockAllowedByCarrier();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ // The user has the final say so if they allow unlock, then the device allows the bootloader
+ // to OEM unlock it.
+ @Override
+ public void setOemUnlockAllowedByUser(boolean allowedByUser) {
+ if (ActivityManager.isUserAMonkey()) {
+ // Prevent a monkey from changing this
+ return;
+ }
+
+ enforceManageUserOemUnlockPermission();
+ enforceUserIsAdmin();
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (!canUserAllowOemUnlock()) {
+ throw new SecurityException("User cannot allow OEM unlock");
+ }
+
+ mOemLock.setOemUnlockAllowedByDevice(allowedByUser);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public boolean isOemUnlockAllowedByUser() {
+ enforceManageUserOemUnlockPermission();
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return mOemLock.isOemUnlockAllowedByDevice();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public boolean canUserAllowOemUnlock() {
+ enforceOemUnlockReadPermission();
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return isOemUnlockAllowedByAdmin() && mOemLock.isOemUnlockAllowedByCarrier();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public boolean isOemUnlockAllowed() {
+ enforceOemUnlockReadPermission();
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return mOemLock.isOemUnlockAllowedByCarrier() &&
+ mOemLock.isOemUnlockAllowedByDevice();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public boolean isDeviceOemUnlocked() {
+ enforceOemUnlockReadPermission();
+
+ String locked = SystemProperties.get(FLASH_LOCK_PROP);
+ switch (locked) {
+ case FLASH_LOCK_UNLOCKED:
+ return true;
+ default:
+ return false;
+ }
+ }
+ };
+
+ private boolean isOemUnlockAllowedByAdmin() {
+ return !UserManager.get(mContext)
+ .hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET, UserHandle.SYSTEM);
+ }
+
+ private void enforceManageCarrierOemUnlockPermission() {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE,
+ "Can't manage OEM unlock allowed by carrier");
+ }
+
+ private void enforceManageUserOemUnlockPermission() {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE,
+ "Can't manage OEM unlock allowed by user");
+ }
+
+ private void enforceOemUnlockReadPermission() {
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission.READ_OEM_UNLOCK_STATE)
+ == PackageManager.PERMISSION_DENIED
+ && mContext.checkCallingOrSelfPermission(Manifest.permission.OEM_UNLOCK_STATE)
+ == PackageManager.PERMISSION_DENIED) {
+ throw new SecurityException("Can't access OEM unlock state. Requires "
+ + "READ_OEM_UNLOCK_STATE or OEM_UNLOCK_STATE permission.");
+ }
+ }
+
+ private void enforceUserIsAdmin() {
+ final int userId = UserHandle.getCallingUserId();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (!UserManager.get(mContext).isUserAdmin(userId)) {
+ throw new SecurityException("Must be an admin user");
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/oemlock/PersistentDataBlockLock.java b/services/core/java/com/android/server/oemlock/PersistentDataBlockLock.java
new file mode 100644
index 0000000..d9362d4
--- /dev/null
+++ b/services/core/java/com/android/server/oemlock/PersistentDataBlockLock.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2017 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 com.android.server.oemlock;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.service.persistentdata.PersistentDataBlockManager;
+import android.util.Slog;
+
+/**
+ * Implementation of the OEM lock using the persistent data block to communicate with the
+ * bootloader.
+ *
+ * The carrier flag is stored as a user restriction on the system user. The user flag is set in the
+ * presistent data block but depends on the carrier flag.
+ */
+class PersistentDataBlockLock extends OemLock {
+ private static final String TAG = "OemLock";
+
+ private Context mContext;
+
+ PersistentDataBlockLock(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
+ // Note: this implementation does not require a signature
+ if (signature != null) {
+ Slog.w(TAG, "Signature provided but is not being used");
+ }
+
+ // Continue using user restriction for backwards compatibility
+ UserManager.get(mContext).setUserRestriction(
+ UserManager.DISALLOW_OEM_UNLOCK, !allowed, UserHandle.SYSTEM);
+
+ if (!allowed) {
+ disallowUnlockIfNotUnlocked();
+ }
+ }
+
+ @Override
+ boolean isOemUnlockAllowedByCarrier() {
+ return !UserManager.get(mContext)
+ .hasUserRestriction(UserManager.DISALLOW_OEM_UNLOCK, UserHandle.SYSTEM);
+ }
+
+ @Override
+ void setOemUnlockAllowedByDevice(boolean allowedByDevice) {
+ // The method name is misleading as it really just means whether or not the device can be
+ // unlocked but doesn't actually do any unlocking.
+ final PersistentDataBlockManager pdbm = (PersistentDataBlockManager)
+ mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+ pdbm.setOemUnlockEnabled(allowedByDevice);
+ }
+
+ @Override
+ boolean isOemUnlockAllowedByDevice() {
+ final PersistentDataBlockManager pdbm = (PersistentDataBlockManager)
+ mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+ return pdbm.getOemUnlockEnabled();
+ }
+
+ /**
+ * Update state to prevent the bootloader from being able to unlock the device unless the device
+ * has already been unlocked by the bootloader in which case it is too late as it would remain
+ * unlocked.
+ */
+ private void disallowUnlockIfNotUnlocked() {
+ final PersistentDataBlockManager pdbm = (PersistentDataBlockManager)
+ mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+ if (pdbm.getFlashLockState() != PersistentDataBlockManager.FLASH_LOCK_UNLOCKED) {
+ pdbm.setOemUnlockEnabled(false);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/oemlock/VendorLock.java b/services/core/java/com/android/server/oemlock/VendorLock.java
new file mode 100644
index 0000000..1b9de36
--- /dev/null
+++ b/services/core/java/com/android/server/oemlock/VendorLock.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2017 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 com.android.server.oemlock;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.oemlock.V1_0.IOemLock;
+import android.hardware.oemlock.V1_0.OemLockSecureStatus;
+import android.hardware.oemlock.V1_0.OemLockStatus;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Slog;
+
+import java.util.ArrayList;
+import java.util.NoSuchElementException;
+
+/**
+ * Uses the OEM lock HAL.
+ */
+class VendorLock extends OemLock {
+ private static final String TAG = "OemLock";
+
+ private Context mContext;
+ private IOemLock mOemLock;
+
+ static IOemLock getOemLockHalService() {
+ try {
+ return IOemLock.getService();
+ } catch (NoSuchElementException e) {
+ Slog.i(TAG, "OemLock HAL not present on device");
+ return null;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ VendorLock(Context context, IOemLock oemLock) {
+ mContext = context;
+ mOemLock = oemLock;
+ }
+
+ @Override
+ void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
+ try {
+ switch (mOemLock.setOemUnlockAllowedByCarrier(allowed, toByteArrayList(signature))) {
+ case OemLockSecureStatus.OK:
+ Slog.i(TAG, "Updated carrier allows OEM lock state to: " + allowed);
+ return;
+
+ case OemLockSecureStatus.INVALID_SIGNATURE:
+ throw new SecurityException(
+ "Invalid signature used in attempt to carrier unlock");
+
+ default:
+ Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL");
+ // Fallthrough
+ case OemLockSecureStatus.FAILED:
+ throw new RuntimeException("Failed to set carrier OEM unlock state");
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to set carrier state with HAL", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
+ boolean isOemUnlockAllowedByCarrier() {
+ final Integer[] requestStatus = new Integer[1];
+ final Boolean[] allowedByCarrier = new Boolean[1];
+
+ try {
+ mOemLock.isOemUnlockAllowedByCarrier((status, allowed) -> {
+ requestStatus[0] = status;
+ allowedByCarrier[0] = allowed;
+ });
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to get carrier state from HAL");
+ throw e.rethrowFromSystemServer();
+ }
+
+ switch (requestStatus[0]) {
+ case OemLockStatus.OK:
+ // Success
+ return allowedByCarrier[0];
+
+ default:
+ Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL");
+ // Fallthrough
+ case OemLockStatus.FAILED:
+ throw new RuntimeException("Failed to get carrier OEM unlock state");
+ }
+ }
+
+ @Override
+ void setOemUnlockAllowedByDevice(boolean allowedByDevice) {
+ try {
+ switch (mOemLock.setOemUnlockAllowedByDevice(allowedByDevice)) {
+ case OemLockSecureStatus.OK:
+ Slog.i(TAG, "Updated device allows OEM lock state to: " + allowedByDevice);
+ return;
+
+ default:
+ Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL");
+ // Fallthrough
+ case OemLockSecureStatus.FAILED:
+ throw new RuntimeException("Failed to set device OEM unlock state");
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to set device state with HAL", e);
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
+ boolean isOemUnlockAllowedByDevice() {
+ final Integer[] requestStatus = new Integer[1];
+ final Boolean[] allowedByDevice = new Boolean[1];
+
+ try {
+ mOemLock.isOemUnlockAllowedByDevice((status, allowed) -> {
+ requestStatus[0] = status;
+ allowedByDevice[0] = allowed;
+ });
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to get devie state from HAL");
+ throw e.rethrowFromSystemServer();
+ }
+
+ switch (requestStatus[0]) {
+ case OemLockStatus.OK:
+ // Success
+ return allowedByDevice[0];
+
+ default:
+ Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL");
+ // Fallthrough
+ case OemLockStatus.FAILED:
+ throw new RuntimeException("Failed to get device OEM unlock state");
+ }
+ }
+
+ private ArrayList toByteArrayList(byte[] data) {
+ if (data == null) {
+ return null;
+ }
+ ArrayList<Byte> result = new ArrayList<Byte>(data.length);
+ for (final byte b : data) {
+ result.add(b);
+ }
+ return result;
+ }
+}
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index c6667a7..a6b05d7 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -31,7 +31,6 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
-import android.service.persistentdata.PersistentDataBlockManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.util.Log;
@@ -519,22 +518,6 @@
android.provider.Settings.Global.SAFE_BOOT_DISALLOWED,
newValue ? 1 : 0);
break;
- case UserManager.DISALLOW_FACTORY_RESET:
- case UserManager.DISALLOW_OEM_UNLOCK:
- if (newValue) {
- PersistentDataBlockManager manager = (PersistentDataBlockManager) context
- .getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
- if (manager != null
- && manager.getOemUnlockEnabled()
- && manager.getFlashLockState()
- != PersistentDataBlockManager.FLASH_LOCK_UNLOCKED) {
- // Only disable OEM unlock if the bootloader is locked. If it's already
- // unlocked, setting the OEM unlock enabled flag to false has no effect
- // (the bootloader would remain unlocked).
- manager.setOemUnlockEnabled(false);
- }
- }
- break;
}
} finally {
Binder.restoreCallingIdentity(id);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 38f35c0..71781ac 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -83,6 +83,7 @@
import com.android.server.net.NetworkPolicyManagerService;
import com.android.server.net.NetworkStatsService;
import com.android.server.notification.NotificationManagerService;
+import com.android.server.oemlock.OemLockService;
import com.android.server.om.OverlayManagerService;
import com.android.server.os.DeviceIdentifiersPolicyService;
import com.android.server.os.SchedulingPolicyService;
@@ -982,12 +983,15 @@
}
traceEnd();
- if (!SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP).equals("")) {
+ final boolean hasPdb = !SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP).equals("");
+ if (hasPdb) {
traceBeginAndSlog("StartPersistentDataBlock");
mSystemServiceManager.startService(PersistentDataBlockService.class);
traceEnd();
+ }
- // Implementation depends on persistent data block
+ if (hasPdb || OemLockService.isHalPresent()) {
+ // Implementation depends on pdb or the OemLock HAL
traceBeginAndSlog("StartOemLockService");
mSystemServiceManager.startService(OemLockService.class);
traceEnd();