| /* |
| * 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); |
| } |
| } |
| } |