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