1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.oemlock; 18 19import android.annotation.Nullable; 20import android.content.Context; 21import android.hardware.oemlock.V1_0.IOemLock; 22import android.hardware.oemlock.V1_0.OemLockSecureStatus; 23import android.hardware.oemlock.V1_0.OemLockStatus; 24import android.os.RemoteException; 25import android.os.UserHandle; 26import android.os.UserManager; 27import android.util.Slog; 28 29import java.util.ArrayList; 30import java.util.NoSuchElementException; 31 32/** 33 * Uses the OEM lock HAL. 34 */ 35class VendorLock extends OemLock { 36 private static final String TAG = "OemLock"; 37 38 private Context mContext; 39 private IOemLock mOemLock; 40 41 static IOemLock getOemLockHalService() { 42 try { 43 return IOemLock.getService(); 44 } catch (NoSuchElementException e) { 45 Slog.i(TAG, "OemLock HAL not present on device"); 46 return null; 47 } catch (RemoteException e) { 48 throw e.rethrowFromSystemServer(); 49 } 50 } 51 52 VendorLock(Context context, IOemLock oemLock) { 53 mContext = context; 54 mOemLock = oemLock; 55 } 56 57 @Override 58 void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) { 59 try { 60 switch (mOemLock.setOemUnlockAllowedByCarrier(allowed, toByteArrayList(signature))) { 61 case OemLockSecureStatus.OK: 62 Slog.i(TAG, "Updated carrier allows OEM lock state to: " + allowed); 63 return; 64 65 case OemLockSecureStatus.INVALID_SIGNATURE: 66 throw new SecurityException( 67 "Invalid signature used in attempt to carrier unlock"); 68 69 default: 70 Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL"); 71 // Fallthrough 72 case OemLockSecureStatus.FAILED: 73 throw new RuntimeException("Failed to set carrier OEM unlock state"); 74 } 75 } catch (RemoteException e) { 76 Slog.e(TAG, "Failed to set carrier state with HAL", e); 77 throw e.rethrowFromSystemServer(); 78 } 79 } 80 81 @Override 82 boolean isOemUnlockAllowedByCarrier() { 83 final Integer[] requestStatus = new Integer[1]; 84 final Boolean[] allowedByCarrier = new Boolean[1]; 85 86 try { 87 mOemLock.isOemUnlockAllowedByCarrier((status, allowed) -> { 88 requestStatus[0] = status; 89 allowedByCarrier[0] = allowed; 90 }); 91 } catch (RemoteException e) { 92 Slog.e(TAG, "Failed to get carrier state from HAL"); 93 throw e.rethrowFromSystemServer(); 94 } 95 96 switch (requestStatus[0]) { 97 case OemLockStatus.OK: 98 // Success 99 return allowedByCarrier[0]; 100 101 default: 102 Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL"); 103 // Fallthrough 104 case OemLockStatus.FAILED: 105 throw new RuntimeException("Failed to get carrier OEM unlock state"); 106 } 107 } 108 109 @Override 110 void setOemUnlockAllowedByDevice(boolean allowedByDevice) { 111 try { 112 switch (mOemLock.setOemUnlockAllowedByDevice(allowedByDevice)) { 113 case OemLockSecureStatus.OK: 114 Slog.i(TAG, "Updated device allows OEM lock state to: " + allowedByDevice); 115 return; 116 117 default: 118 Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL"); 119 // Fallthrough 120 case OemLockSecureStatus.FAILED: 121 throw new RuntimeException("Failed to set device OEM unlock state"); 122 } 123 } catch (RemoteException e) { 124 Slog.e(TAG, "Failed to set device state with HAL", e); 125 throw e.rethrowFromSystemServer(); 126 } 127 } 128 129 @Override 130 boolean isOemUnlockAllowedByDevice() { 131 final Integer[] requestStatus = new Integer[1]; 132 final Boolean[] allowedByDevice = new Boolean[1]; 133 134 try { 135 mOemLock.isOemUnlockAllowedByDevice((status, allowed) -> { 136 requestStatus[0] = status; 137 allowedByDevice[0] = allowed; 138 }); 139 } catch (RemoteException e) { 140 Slog.e(TAG, "Failed to get devie state from HAL"); 141 throw e.rethrowFromSystemServer(); 142 } 143 144 switch (requestStatus[0]) { 145 case OemLockStatus.OK: 146 // Success 147 return allowedByDevice[0]; 148 149 default: 150 Slog.e(TAG, "Unknown return value indicates code is out of sync with HAL"); 151 // Fallthrough 152 case OemLockStatus.FAILED: 153 throw new RuntimeException("Failed to get device OEM unlock state"); 154 } 155 } 156 157 private ArrayList toByteArrayList(byte[] data) { 158 if (data == null) { 159 return null; 160 } 161 ArrayList<Byte> result = new ArrayList<Byte>(data.length); 162 for (final byte b : data) { 163 result.add(b); 164 } 165 return result; 166 } 167} 168