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 20 .STRONG_AUTH_NOT_REQUIRED; 21 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker 22 .STRONG_AUTH_REQUIRED_AFTER_TIMEOUT; 23 24 import android.app.AlarmManager; 25 import android.app.AlarmManager.OnAlarmListener; 26 import android.app.admin.DevicePolicyManager; 27 import android.app.trust.IStrongAuthTracker; 28 import android.content.Context; 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 LockSettingsStrongAuth(Context context)66 public LockSettingsStrongAuth(Context context) { 67 mContext = context; 68 mDefaultStrongAuthFlags = StrongAuthTracker.getDefaultFlags(context); 69 mAlarmManager = context.getSystemService(AlarmManager.class); 70 } 71 handleAddStrongAuthTracker(IStrongAuthTracker tracker)72 private void handleAddStrongAuthTracker(IStrongAuthTracker tracker) { 73 mTrackers.register(tracker); 74 75 for (int i = 0; i < mStrongAuthForUser.size(); i++) { 76 int key = mStrongAuthForUser.keyAt(i); 77 int value = mStrongAuthForUser.valueAt(i); 78 try { 79 tracker.onStrongAuthRequiredChanged(value, key); 80 } catch (RemoteException e) { 81 Slog.e(TAG, "Exception while adding StrongAuthTracker.", e); 82 } 83 } 84 } 85 handleRemoveStrongAuthTracker(IStrongAuthTracker tracker)86 private void handleRemoveStrongAuthTracker(IStrongAuthTracker tracker) { 87 mTrackers.unregister(tracker); 88 } 89 handleRequireStrongAuth(int strongAuthReason, int userId)90 private void handleRequireStrongAuth(int strongAuthReason, int userId) { 91 if (userId == UserHandle.USER_ALL) { 92 for (int i = 0; i < mStrongAuthForUser.size(); i++) { 93 int key = mStrongAuthForUser.keyAt(i); 94 handleRequireStrongAuthOneUser(strongAuthReason, key); 95 } 96 } else { 97 handleRequireStrongAuthOneUser(strongAuthReason, userId); 98 } 99 } 100 handleRequireStrongAuthOneUser(int strongAuthReason, int userId)101 private void handleRequireStrongAuthOneUser(int strongAuthReason, int userId) { 102 int oldValue = mStrongAuthForUser.get(userId, mDefaultStrongAuthFlags); 103 int newValue = strongAuthReason == STRONG_AUTH_NOT_REQUIRED 104 ? STRONG_AUTH_NOT_REQUIRED 105 : (oldValue | strongAuthReason); 106 if (oldValue != newValue) { 107 mStrongAuthForUser.put(userId, newValue); 108 notifyStrongAuthTrackers(newValue, userId); 109 } 110 } 111 handleRemoveUser(int userId)112 private void handleRemoveUser(int userId) { 113 int index = mStrongAuthForUser.indexOfKey(userId); 114 if (index >= 0) { 115 mStrongAuthForUser.removeAt(index); 116 notifyStrongAuthTrackers(mDefaultStrongAuthFlags, userId); 117 } 118 } 119 handleScheduleStrongAuthTimeout(int userId)120 private void handleScheduleStrongAuthTimeout(int userId) { 121 final DevicePolicyManager dpm = 122 (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); 123 long when = SystemClock.elapsedRealtime() + dpm.getRequiredStrongAuthTimeout(null, userId); 124 // cancel current alarm listener for the user (if there was one) 125 StrongAuthTimeoutAlarmListener alarm = mStrongAuthTimeoutAlarmListenerForUser.get(userId); 126 if (alarm != null) { 127 mAlarmManager.cancel(alarm); 128 } else { 129 alarm = new StrongAuthTimeoutAlarmListener(userId); 130 mStrongAuthTimeoutAlarmListenerForUser.put(userId, alarm); 131 } 132 // schedule a new alarm listener for the user 133 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when, STRONG_AUTH_TIMEOUT_ALARM_TAG, 134 alarm, mHandler); 135 } 136 notifyStrongAuthTrackers(int strongAuthReason, int userId)137 private void notifyStrongAuthTrackers(int strongAuthReason, int userId) { 138 int i = mTrackers.beginBroadcast(); 139 try { 140 while (i > 0) { 141 i--; 142 try { 143 mTrackers.getBroadcastItem(i).onStrongAuthRequiredChanged( 144 strongAuthReason, userId); 145 } catch (RemoteException e) { 146 Slog.e(TAG, "Exception while notifying StrongAuthTracker.", e); 147 } 148 } 149 } finally { 150 mTrackers.finishBroadcast(); 151 } 152 } 153 registerStrongAuthTracker(IStrongAuthTracker tracker)154 public void registerStrongAuthTracker(IStrongAuthTracker tracker) { 155 mHandler.obtainMessage(MSG_REGISTER_TRACKER, tracker).sendToTarget(); 156 } 157 unregisterStrongAuthTracker(IStrongAuthTracker tracker)158 public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) { 159 mHandler.obtainMessage(MSG_UNREGISTER_TRACKER, tracker).sendToTarget(); 160 } 161 removeUser(int userId)162 public void removeUser(int userId) { 163 final int argNotUsed = 0; 164 mHandler.obtainMessage(MSG_REMOVE_USER, userId, argNotUsed).sendToTarget(); 165 } 166 requireStrongAuth(int strongAuthReason, int userId)167 public void requireStrongAuth(int strongAuthReason, int userId) { 168 if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_SYSTEM) { 169 mHandler.obtainMessage(MSG_REQUIRE_STRONG_AUTH, strongAuthReason, 170 userId).sendToTarget(); 171 } else { 172 throw new IllegalArgumentException( 173 "userId must be an explicit user id or USER_ALL"); 174 } 175 } 176 reportUnlock(int userId)177 public void reportUnlock(int userId) { 178 requireStrongAuth(STRONG_AUTH_NOT_REQUIRED, userId); 179 } 180 reportSuccessfulStrongAuthUnlock(int userId)181 public void reportSuccessfulStrongAuthUnlock(int userId) { 182 final int argNotUsed = 0; 183 mHandler.obtainMessage(MSG_SCHEDULE_STRONG_AUTH_TIMEOUT, userId, argNotUsed).sendToTarget(); 184 } 185 186 private class StrongAuthTimeoutAlarmListener implements OnAlarmListener { 187 188 private final int mUserId; 189 StrongAuthTimeoutAlarmListener(int userId)190 public StrongAuthTimeoutAlarmListener(int userId) { 191 mUserId = userId; 192 } 193 194 @Override onAlarm()195 public void onAlarm() { 196 requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_TIMEOUT, mUserId); 197 } 198 } 199 200 private final Handler mHandler = new Handler() { 201 @Override 202 public void handleMessage(Message msg) { 203 switch (msg.what) { 204 case MSG_REGISTER_TRACKER: 205 handleAddStrongAuthTracker((IStrongAuthTracker) msg.obj); 206 break; 207 case MSG_UNREGISTER_TRACKER: 208 handleRemoveStrongAuthTracker((IStrongAuthTracker) msg.obj); 209 break; 210 case MSG_REQUIRE_STRONG_AUTH: 211 handleRequireStrongAuth(msg.arg1, msg.arg2); 212 break; 213 case MSG_REMOVE_USER: 214 handleRemoveUser(msg.arg1); 215 break; 216 case MSG_SCHEDULE_STRONG_AUTH_TIMEOUT: 217 handleScheduleStrongAuthTimeout(msg.arg1); 218 break; 219 } 220 } 221 }; 222 223 } 224