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