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; 18 19import com.android.internal.widget.LockPatternUtils; 20import com.android.internal.widget.LockPatternUtils.StrongAuthTracker; 21 22import android.app.trust.IStrongAuthTracker; 23import android.os.DeadObjectException; 24import android.os.Handler; 25import android.os.Message; 26import android.os.RemoteException; 27import android.os.UserHandle; 28import android.util.Slog; 29import android.util.SparseIntArray; 30 31import java.util.ArrayList; 32 33import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED; 34 35/** 36 * Keeps track of requests for strong authentication. 37 */ 38public class LockSettingsStrongAuth { 39 40 private static final String TAG = "LockSettings"; 41 42 private static final int MSG_REQUIRE_STRONG_AUTH = 1; 43 private static final int MSG_REGISTER_TRACKER = 2; 44 private static final int MSG_UNREGISTER_TRACKER = 3; 45 private static final int MSG_REMOVE_USER = 4; 46 47 private final ArrayList<IStrongAuthTracker> mStrongAuthTrackers = new ArrayList<>(); 48 private final SparseIntArray mStrongAuthForUser = new SparseIntArray(); 49 50 private void handleAddStrongAuthTracker(IStrongAuthTracker tracker) { 51 for (int i = 0; i < mStrongAuthTrackers.size(); i++) { 52 if (mStrongAuthTrackers.get(i).asBinder() == tracker.asBinder()) { 53 return; 54 } 55 } 56 mStrongAuthTrackers.add(tracker); 57 58 for (int i = 0; i < mStrongAuthForUser.size(); i++) { 59 int key = mStrongAuthForUser.keyAt(i); 60 int value = mStrongAuthForUser.valueAt(i); 61 try { 62 tracker.onStrongAuthRequiredChanged(value, key); 63 } catch (RemoteException e) { 64 Slog.e(TAG, "Exception while adding StrongAuthTracker.", e); 65 } 66 } 67 } 68 69 private void handleRemoveStrongAuthTracker(IStrongAuthTracker tracker) { 70 for (int i = 0; i < mStrongAuthTrackers.size(); i++) { 71 if (mStrongAuthTrackers.get(i).asBinder() == tracker.asBinder()) { 72 mStrongAuthTrackers.remove(i); 73 return; 74 } 75 } 76 } 77 78 private void handleRequireStrongAuth(int strongAuthReason, int userId) { 79 if (userId == UserHandle.USER_ALL) { 80 for (int i = 0; i < mStrongAuthForUser.size(); i++) { 81 int key = mStrongAuthForUser.keyAt(i); 82 handleRequireStrongAuthOneUser(strongAuthReason, key); 83 } 84 } else { 85 handleRequireStrongAuthOneUser(strongAuthReason, userId); 86 } 87 } 88 89 private void handleRequireStrongAuthOneUser(int strongAuthReason, int userId) { 90 int oldValue = mStrongAuthForUser.get(userId, LockPatternUtils.StrongAuthTracker.DEFAULT); 91 int newValue = strongAuthReason == STRONG_AUTH_NOT_REQUIRED 92 ? STRONG_AUTH_NOT_REQUIRED 93 : (oldValue | strongAuthReason); 94 if (oldValue != newValue) { 95 mStrongAuthForUser.put(userId, newValue); 96 notifyStrongAuthTrackers(newValue, userId); 97 } 98 } 99 100 private void handleRemoveUser(int userId) { 101 int index = mStrongAuthForUser.indexOfKey(userId); 102 if (index >= 0) { 103 mStrongAuthForUser.removeAt(index); 104 notifyStrongAuthTrackers(StrongAuthTracker.DEFAULT, userId); 105 } 106 } 107 108 private void notifyStrongAuthTrackers(int strongAuthReason, int userId) { 109 for (int i = 0; i < mStrongAuthTrackers.size(); i++) { 110 try { 111 mStrongAuthTrackers.get(i).onStrongAuthRequiredChanged(strongAuthReason, userId); 112 } catch (DeadObjectException e) { 113 Slog.d(TAG, "Removing dead StrongAuthTracker."); 114 mStrongAuthTrackers.remove(i); 115 i--; 116 } catch (RemoteException e) { 117 Slog.e(TAG, "Exception while notifying StrongAuthTracker.", e); 118 } 119 } 120 } 121 122 public void registerStrongAuthTracker(IStrongAuthTracker tracker) { 123 mHandler.obtainMessage(MSG_REGISTER_TRACKER, tracker).sendToTarget(); 124 } 125 126 public void unregisterStrongAuthTracker(IStrongAuthTracker tracker) { 127 mHandler.obtainMessage(MSG_UNREGISTER_TRACKER, tracker).sendToTarget(); 128 } 129 130 public void removeUser(int userId) { 131 mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget(); 132 } 133 134 public void requireStrongAuth(int strongAuthReason, int userId) { 135 if (userId == UserHandle.USER_ALL || userId >= UserHandle.USER_OWNER) { 136 mHandler.obtainMessage(MSG_REQUIRE_STRONG_AUTH, strongAuthReason, 137 userId).sendToTarget(); 138 } else { 139 throw new IllegalArgumentException( 140 "userId must be an explicit user id or USER_ALL"); 141 } 142 } 143 144 public void reportUnlock(int userId) { 145 requireStrongAuth(STRONG_AUTH_NOT_REQUIRED, userId); 146 } 147 148 private final Handler mHandler = new Handler() { 149 @Override 150 public void handleMessage(Message msg) { 151 switch (msg.what) { 152 case MSG_REGISTER_TRACKER: 153 handleAddStrongAuthTracker((IStrongAuthTracker) msg.obj); 154 break; 155 case MSG_UNREGISTER_TRACKER: 156 handleRemoveStrongAuthTracker((IStrongAuthTracker) msg.obj); 157 break; 158 case MSG_REQUIRE_STRONG_AUTH: 159 handleRequireStrongAuth(msg.arg1, msg.arg2); 160 break; 161 case MSG_REMOVE_USER: 162 handleRemoveUser(msg.arg1); 163 break; 164 } 165 } 166 }; 167} 168