1 /* 2 * Copyright (C) 2015 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 17 package com.android.server.locksettings; 18 19 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED; 20 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT; 21 22 import android.app.AlarmManager; 23 import android.app.AlarmManager.OnAlarmListener; 24 import android.app.admin.DevicePolicyManager; 25 import android.app.trust.IStrongAuthTracker; 26 import android.content.Context; 27 import android.content.pm.PackageManager; 28 import android.hardware.fingerprint.FingerprintManager; 29 import android.os.Handler; 30 import android.os.Message; 31 import android.os.RemoteCallbackList; 32 import android.os.RemoteException; 33 import android.os.SystemClock; 34 import android.os.UserHandle; 35 import android.util.ArrayMap; 36 import android.util.Slog; 37 import android.util.SparseIntArray; 38 39 import com.android.internal.widget.LockPatternUtils.StrongAuthTracker; 40 41 /** 42 * Keeps track of requests for strong authentication. 43 */ 44 public class LockSettingsStrongAuth { 45 46 private static final String TAG = "LockSettings"; 47 48 private static final int MSG_REQUIRE_STRONG_AUTH = 1; 49 private static final int MSG_REGISTER_TRACKER = 2; 50 private static final int MSG_UNREGISTER_TRACKER = 3; 51 private static final int MSG_REMOVE_USER = 4; 52 private static final int MSG_SCHEDULE_STRONG_AUTH_TIMEOUT = 5; 53 54 private static final String STRONG_AUTH_TIMEOUT_ALARM_TAG = 55 "LockSettingsStrongAuth.timeoutForUser"; 56 57 private final RemoteCallbackList<IStrongAuthTracker> mTrackers = new RemoteCallbackList<>(); 58 private final SparseIntArray mStrongAuthForUser = new SparseIntArray(); 59 private final ArrayMap<Integer, StrongAuthTimeoutAlarmListener> 60 mStrongAuthTimeoutAlarmListenerForUser = new ArrayMap<>(); 61 private final int mDefaultStrongAuthFlags; 62 private final Context mContext; 63 64 private AlarmManager mAlarmManager; 65 private FingerprintManager mFingerprintManager; 66 LockSettingsStrongAuth(Context context)67 public LockSettingsStrongAuth(Context context) { 68 mContext = context; 69 mDefaultStrongAuthFlags = StrongAuthTracker.getDefaultFlags(context); 70 mAlarmManager = context.getSystemService(AlarmManager.class); 71 } 72 systemReady()73 public void systemReady() { 74 final PackageManager pm = mContext.getPackageManager(); 75 if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { 76 mFingerprintManager = mContext.getSystemService(FingerprintManager.class); 77 } 78 } 79 handleAddStrongAuthTracker(IStrongAuthTracker tracker)80 private void handleAddStrongAuthTracker(IStrongAuthTracker tracker) { 81 mTrackers.register(tracker); 82 83 for (int i = 0; i < mStrongAuthForUser.size(); i++) { 84 int key = mStrongAuthForUser.keyAt(i); 85 int value = mStrongAuthForUser.valueAt(i); 86 try { 87 tracker.onStrongAuthRequiredChanged(value, key); 88 } catch (RemoteException e) { 89 Slog.e(TAG, "Exception while adding StrongAuthTracker.", e); 90 } 91 } 92 } 93 handleRemoveStrongAuthTracker(IStrongAuthTracker tracker)94 private void handleRemoveStrongAuthTracker(IStrongAuthTracker tracker) { 95 mTrackers.unregister(tracker); 96 } 97 handleRequireStrongAuth(int strongAuthReason, int userId)98 private void handleRequireStrongAuth(int strongAuthReason, int userId) { 99 if (userId == UserHandle.USER_ALL) { 100 for (int i = 0; i < mStrongAuthForUser.size(); i++) { 101 int key = mStrongAuthForUser.keyAt(i); 102 handleRequireStrongAuthOneUser(strongAuthReason, key); 103 } 104 } else { 105 handleRequireStrongAuthOneUser(strongAuthReason, userId); 106 } 107 } 108 handleRequireStrongAuthOneUser(int strongAuthReason, int userId)109 private void handleRequireStrongAuthOneUser(int strongAuthReason, int userId) { 110 int oldValue = mStrongAuthForUser.get(userId, mDefaultStrongAuthFlags); 111 int newValue = strongAuthReason == STRONG_AUTH_NOT_REQUIRED 112 ? STRONG_AUTH_NOT_REQUIRED 113 : (oldValue | strongAuthReason); 114 if (oldValue != newValue) { 115 mStrongAuthForUser.put(userId, newValue); 116 notifyStrongAuthTrackers(newValue, userId); 117 } 118 } 119 handleRemoveUser(int userId)120 private void handleRemoveUser(int userId) { 121 int index = mStrongAuthForUser.indexOfKey(userId); 122 if (index >= 0) { 123 mStrongAuthForUser.removeAt(index); 124 notifyStrongAuthTrackers(mDefaultStrongAuthFlags, userId); 125 } 126 } 127 handleScheduleStrongAuthTimeout(int userId)128 private void handleScheduleStrongAuthTimeout(int userId) { 129 final DevicePolicyManager dpm = 130 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 131 long when = SystemClock.elapsedRealtime() + dpm.getRequiredStrongAuthTimeout(null, userId); 132 // cancel current alarm listener for the user (if there was one) 133 StrongAuthTimeoutAlarmListener alarm = mStrongAuthTimeoutAlarmListenerForUser.get(userId); 134 if (alarm != null) { 135 mAlarmManager.cancel(alarm); 136 } else { 137 alarm = new StrongAuthTimeoutAlarmListener(userId); 138 mStrongAuthTimeoutAlarmListenerForUser.put(userId, alarm); 139 } 140 // schedule a new alarm listener for the user 141 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when, STRONG_AUTH_TIMEOUT_ALARM_TAG, 142 alarm, mHandler); 143 } 144 notifyStrongAuthTrackers(int strongAuthReason, int userId)145 private void notifyStrongAuthTrackers(int strongAuthReason, int userId) { 146 int i = mTrackers.beginBroadcast(); 147 try { 148 while (i > 0) { 149 i--; 150 try { 151 mTrackers.getBroadcastItem(i).onStrongAuthRequiredChanged( 152 strongAuthReason, userId); 153 } catch (RemoteException e) { 154 Slog.e(TAG, "Exception while notifying StrongAuthTracker.", e); 155 } 156 } 157 } finally { 158 mTrackers.finishBroadcast(); 159 } 160 } 161 registerStrongAuthTracker(IStrongAuthTracker tracker)162 public void registerStrongAuthTracker(IStrongAuthTracker tracker) { 163 mHandler.obtainMessage(MSG_REGISTER_TRACKER, tracker).sendToTarget(); 164 } 165 unregisterStrongAuthTracker(IStrongAuthTracker tracker)166 public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) { 167 mHandler.obtainMessage(MSG_UNREGISTER_TRACKER, tracker).sendToTarget(); 168 } 169 removeUser(int userId)170 public void removeUser(int userId) { 171 final int argNotUsed = 0; 172 mHandler.obtainMessage(MSG_REMOVE_USER, userId, argNotUsed).sendToTarget(); 173 } 174 requireStrongAuth(int strongAuthReason, int userId)175 public void requireStrongAuth(int strongAuthReason, int userId) { 176 if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_SYSTEM) { 177 mHandler.obtainMessage(MSG_REQUIRE_STRONG_AUTH, strongAuthReason, 178 userId).sendToTarget(); 179 } else { 180 throw new IllegalArgumentException( 181 "userId must be an explicit user id or USER_ALL"); 182 } 183 } 184 reportUnlock(int userId)185 public void reportUnlock(int userId) { 186 requireStrongAuth(STRONG_AUTH_NOT_REQUIRED, userId); 187 } 188 reportSuccessfulStrongAuthUnlock(int userId)189 public void reportSuccessfulStrongAuthUnlock(int userId) { 190 if (mFingerprintManager != null) { 191 byte[] token = null; /* TODO: pass real auth token once fp HAL supports it */ 192 mFingerprintManager.resetTimeout(token); 193 } 194 195 final int argNotUsed = 0; 196 mHandler.obtainMessage(MSG_SCHEDULE_STRONG_AUTH_TIMEOUT, userId, argNotUsed).sendToTarget(); 197 } 198 199 private class StrongAuthTimeoutAlarmListener implements OnAlarmListener { 200 201 private final int mUserId; 202 StrongAuthTimeoutAlarmListener(int userId)203 public StrongAuthTimeoutAlarmListener(int userId) { 204 mUserId = userId; 205 } 206 207 @Override onAlarm()208 public void onAlarm() { 209 requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_TIMEOUT, mUserId); 210 } 211 } 212 213 private final Handler mHandler = new Handler() { 214 @Override 215 public void handleMessage(Message msg) { 216 switch (msg.what) { 217 case MSG_REGISTER_TRACKER: 218 handleAddStrongAuthTracker((IStrongAuthTracker) msg.obj); 219 break; 220 case MSG_UNREGISTER_TRACKER: 221 handleRemoveStrongAuthTracker((IStrongAuthTracker) msg.obj); 222 break; 223 case MSG_REQUIRE_STRONG_AUTH: 224 handleRequireStrongAuth(msg.arg1, msg.arg2); 225 break; 226 case MSG_REMOVE_USER: 227 handleRemoveUser(msg.arg1); 228 break; 229 case MSG_SCHEDULE_STRONG_AUTH_TIMEOUT: 230 handleScheduleStrongAuthTimeout(msg.arg1); 231 break; 232 } 233 } 234 }; 235 236 } 237