Home | History | Annotate | Download | only in server
      1 /*
      2  * Copyright (C) 2010 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.content.PackageMonitor;
     20 import com.android.internal.os.storage.ExternalStorageFormatter;
     21 import com.android.internal.util.FastXmlSerializer;
     22 import com.android.internal.util.JournaledFile;
     23 import com.android.internal.util.XmlUtils;
     24 import com.android.internal.widget.LockPatternUtils;
     25 
     26 import org.xmlpull.v1.XmlPullParser;
     27 import org.xmlpull.v1.XmlPullParserException;
     28 import org.xmlpull.v1.XmlSerializer;
     29 
     30 import android.app.Activity;
     31 import android.app.AlarmManager;
     32 import android.app.PendingIntent;
     33 import android.app.admin.DeviceAdminInfo;
     34 import android.app.admin.DeviceAdminReceiver;
     35 import android.app.admin.DevicePolicyManager;
     36 import android.app.admin.IDevicePolicyManager;
     37 import android.content.BroadcastReceiver;
     38 import android.content.ComponentName;
     39 import android.content.ContentResolver;
     40 import android.content.Context;
     41 import android.content.Intent;
     42 import android.content.IntentFilter;
     43 import android.content.pm.PackageManager;
     44 import android.content.pm.PackageManager.NameNotFoundException;
     45 import android.content.pm.ResolveInfo;
     46 import android.os.Binder;
     47 import android.os.Environment;
     48 import android.os.Handler;
     49 import android.os.IBinder;
     50 import android.os.IPowerManager;
     51 import android.os.PowerManager;
     52 import android.os.RecoverySystem;
     53 import android.os.RemoteCallback;
     54 import android.os.RemoteException;
     55 import android.os.ServiceManager;
     56 import android.os.SystemClock;
     57 import android.os.SystemProperties;
     58 import android.provider.Settings;
     59 import android.util.PrintWriterPrinter;
     60 import android.util.Printer;
     61 import android.util.Slog;
     62 import android.util.Xml;
     63 import android.view.IWindowManager;
     64 import android.view.WindowManagerPolicy;
     65 
     66 import java.io.File;
     67 import java.io.FileDescriptor;
     68 import java.io.FileInputStream;
     69 import java.io.FileNotFoundException;
     70 import java.io.FileOutputStream;
     71 import java.io.IOException;
     72 import java.io.PrintWriter;
     73 import java.text.DateFormat;
     74 import java.util.ArrayList;
     75 import java.util.Date;
     76 import java.util.HashMap;
     77 import java.util.List;
     78 import java.util.Set;
     79 
     80 /**
     81  * Implementation of the device policy APIs.
     82  */
     83 public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     84     private static final String TAG = "DevicePolicyManagerService";
     85 
     86     private static final int REQUEST_EXPIRE_PASSWORD = 5571;
     87 
     88     private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * 86400 * 1000; // 5 days, in ms
     89 
     90     protected static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION
     91             = "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION";
     92 
     93     private static final long MS_PER_DAY = 86400 * 1000;
     94 
     95     final Context mContext;
     96     final MyPackageMonitor mMonitor;
     97     final PowerManager.WakeLock mWakeLock;
     98 
     99     IPowerManager mIPowerManager;
    100     IWindowManager mIWindowManager;
    101 
    102     int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
    103     int mActivePasswordLength = 0;
    104     int mActivePasswordUpperCase = 0;
    105     int mActivePasswordLowerCase = 0;
    106     int mActivePasswordLetters = 0;
    107     int mActivePasswordNumeric = 0;
    108     int mActivePasswordSymbols = 0;
    109     int mActivePasswordNonLetter = 0;
    110     int mFailedPasswordAttempts = 0;
    111 
    112     int mPasswordOwner = -1;
    113     Handler mHandler = new Handler();
    114 
    115     final HashMap<ComponentName, ActiveAdmin> mAdminMap
    116             = new HashMap<ComponentName, ActiveAdmin>();
    117     final ArrayList<ActiveAdmin> mAdminList
    118             = new ArrayList<ActiveAdmin>();
    119 
    120     BroadcastReceiver mReceiver = new BroadcastReceiver() {
    121         @Override
    122         public void onReceive(Context context, Intent intent) {
    123             String action = intent.getAction();
    124             if (Intent.ACTION_BOOT_COMPLETED.equals(action)
    125                     || ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) {
    126                 Slog.v(TAG, "Sending password expiration notifications for action " + action);
    127                 mHandler.post(new Runnable() {
    128                     public void run() {
    129                         handlePasswordExpirationNotification();
    130                     }
    131                 });
    132             }
    133         }
    134     };
    135 
    136     static class ActiveAdmin {
    137         final DeviceAdminInfo info;
    138 
    139         int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
    140 
    141         static final int DEF_MINIMUM_PASSWORD_LENGTH = 0;
    142         int minimumPasswordLength = DEF_MINIMUM_PASSWORD_LENGTH;
    143 
    144         static final int DEF_PASSWORD_HISTORY_LENGTH = 0;
    145         int passwordHistoryLength = DEF_PASSWORD_HISTORY_LENGTH;
    146 
    147         static final int DEF_MINIMUM_PASSWORD_UPPER_CASE = 0;
    148         int minimumPasswordUpperCase = DEF_MINIMUM_PASSWORD_UPPER_CASE;
    149 
    150         static final int DEF_MINIMUM_PASSWORD_LOWER_CASE = 0;
    151         int minimumPasswordLowerCase = DEF_MINIMUM_PASSWORD_LOWER_CASE;
    152 
    153         static final int DEF_MINIMUM_PASSWORD_LETTERS = 1;
    154         int minimumPasswordLetters = DEF_MINIMUM_PASSWORD_LETTERS;
    155 
    156         static final int DEF_MINIMUM_PASSWORD_NUMERIC = 1;
    157         int minimumPasswordNumeric = DEF_MINIMUM_PASSWORD_NUMERIC;
    158 
    159         static final int DEF_MINIMUM_PASSWORD_SYMBOLS = 1;
    160         int minimumPasswordSymbols = DEF_MINIMUM_PASSWORD_SYMBOLS;
    161 
    162         static final int DEF_MINIMUM_PASSWORD_NON_LETTER = 0;
    163         int minimumPasswordNonLetter = DEF_MINIMUM_PASSWORD_NON_LETTER;
    164 
    165         static final long DEF_MAXIMUM_TIME_TO_UNLOCK = 0;
    166         long maximumTimeToUnlock = DEF_MAXIMUM_TIME_TO_UNLOCK;
    167 
    168         static final int DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE = 0;
    169         int maximumFailedPasswordsForWipe = DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE;
    170 
    171         static final long DEF_PASSWORD_EXPIRATION_TIMEOUT = 0;
    172         long passwordExpirationTimeout = DEF_PASSWORD_EXPIRATION_TIMEOUT;
    173 
    174         static final long DEF_PASSWORD_EXPIRATION_DATE = 0;
    175         long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE;
    176 
    177         boolean encryptionRequested = false;
    178         boolean disableCamera = false;
    179 
    180         // TODO: review implementation decisions with frameworks team
    181         boolean specifiesGlobalProxy = false;
    182         String globalProxySpec = null;
    183         String globalProxyExclusionList = null;
    184 
    185         ActiveAdmin(DeviceAdminInfo _info) {
    186             info = _info;
    187         }
    188 
    189         int getUid() { return info.getActivityInfo().applicationInfo.uid; }
    190 
    191         void writeToXml(XmlSerializer out)
    192                 throws IllegalArgumentException, IllegalStateException, IOException {
    193             out.startTag(null, "policies");
    194             info.writePoliciesToXml(out);
    195             out.endTag(null, "policies");
    196             if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
    197                 out.startTag(null, "password-quality");
    198                 out.attribute(null, "value", Integer.toString(passwordQuality));
    199                 out.endTag(null, "password-quality");
    200                 if (minimumPasswordLength != DEF_MINIMUM_PASSWORD_LENGTH) {
    201                     out.startTag(null, "min-password-length");
    202                     out.attribute(null, "value", Integer.toString(minimumPasswordLength));
    203                     out.endTag(null, "min-password-length");
    204                 }
    205                 if(passwordHistoryLength != DEF_PASSWORD_HISTORY_LENGTH) {
    206                     out.startTag(null, "password-history-length");
    207                     out.attribute(null, "value", Integer.toString(passwordHistoryLength));
    208                     out.endTag(null, "password-history-length");
    209                 }
    210                 if (minimumPasswordUpperCase != DEF_MINIMUM_PASSWORD_UPPER_CASE) {
    211                     out.startTag(null, "min-password-uppercase");
    212                     out.attribute(null, "value", Integer.toString(minimumPasswordUpperCase));
    213                     out.endTag(null, "min-password-uppercase");
    214                 }
    215                 if (minimumPasswordLowerCase != DEF_MINIMUM_PASSWORD_LOWER_CASE) {
    216                     out.startTag(null, "min-password-lowercase");
    217                     out.attribute(null, "value", Integer.toString(minimumPasswordLowerCase));
    218                     out.endTag(null, "min-password-lowercase");
    219                 }
    220                 if (minimumPasswordLetters != DEF_MINIMUM_PASSWORD_LETTERS) {
    221                     out.startTag(null, "min-password-letters");
    222                     out.attribute(null, "value", Integer.toString(minimumPasswordLetters));
    223                     out.endTag(null, "min-password-letters");
    224                 }
    225                 if (minimumPasswordNumeric != DEF_MINIMUM_PASSWORD_NUMERIC) {
    226                     out.startTag(null, "min-password-numeric");
    227                     out.attribute(null, "value", Integer.toString(minimumPasswordNumeric));
    228                     out.endTag(null, "min-password-numeric");
    229                 }
    230                 if (minimumPasswordSymbols != DEF_MINIMUM_PASSWORD_SYMBOLS) {
    231                     out.startTag(null, "min-password-symbols");
    232                     out.attribute(null, "value", Integer.toString(minimumPasswordSymbols));
    233                     out.endTag(null, "min-password-symbols");
    234                 }
    235                 if (minimumPasswordNonLetter > DEF_MINIMUM_PASSWORD_NON_LETTER) {
    236                     out.startTag(null, "min-password-nonletter");
    237                     out.attribute(null, "value", Integer.toString(minimumPasswordNonLetter));
    238                     out.endTag(null, "min-password-nonletter");
    239                 }
    240             }
    241             if (maximumTimeToUnlock != DEF_MAXIMUM_TIME_TO_UNLOCK) {
    242                 out.startTag(null, "max-time-to-unlock");
    243                 out.attribute(null, "value", Long.toString(maximumTimeToUnlock));
    244                 out.endTag(null, "max-time-to-unlock");
    245             }
    246             if (maximumFailedPasswordsForWipe != DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
    247                 out.startTag(null, "max-failed-password-wipe");
    248                 out.attribute(null, "value", Integer.toString(maximumFailedPasswordsForWipe));
    249                 out.endTag(null, "max-failed-password-wipe");
    250             }
    251             if (specifiesGlobalProxy) {
    252                 out.startTag(null, "specifies-global-proxy");
    253                 out.attribute(null, "value", Boolean.toString(specifiesGlobalProxy));
    254                 out.endTag(null, "specifies_global_proxy");
    255                 if (globalProxySpec != null) {
    256                     out.startTag(null, "global-proxy-spec");
    257                     out.attribute(null, "value", globalProxySpec);
    258                     out.endTag(null, "global-proxy-spec");
    259                 }
    260                 if (globalProxyExclusionList != null) {
    261                     out.startTag(null, "global-proxy-exclusion-list");
    262                     out.attribute(null, "value", globalProxyExclusionList);
    263                     out.endTag(null, "global-proxy-exclusion-list");
    264                 }
    265             }
    266             if (passwordExpirationTimeout != DEF_PASSWORD_EXPIRATION_TIMEOUT) {
    267                 out.startTag(null, "password-expiration-timeout");
    268                 out.attribute(null, "value", Long.toString(passwordExpirationTimeout));
    269                 out.endTag(null, "password-expiration-timeout");
    270             }
    271             if (passwordExpirationDate != DEF_PASSWORD_EXPIRATION_DATE) {
    272                 out.startTag(null, "password-expiration-date");
    273                 out.attribute(null, "value", Long.toString(passwordExpirationDate));
    274                 out.endTag(null, "password-expiration-date");
    275             }
    276             if (encryptionRequested) {
    277                 out.startTag(null, "encryption-requested");
    278                 out.attribute(null, "value", Boolean.toString(encryptionRequested));
    279                 out.endTag(null, "encryption-requested");
    280             }
    281             if (disableCamera) {
    282                 out.startTag(null, "disable-camera");
    283                 out.attribute(null, "value", Boolean.toString(disableCamera));
    284                 out.endTag(null, "disable-camera");
    285             }
    286         }
    287 
    288         void readFromXml(XmlPullParser parser)
    289                 throws XmlPullParserException, IOException {
    290             int outerDepth = parser.getDepth();
    291             int type;
    292             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
    293                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
    294                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
    295                     continue;
    296                 }
    297                 String tag = parser.getName();
    298                 if ("policies".equals(tag)) {
    299                     info.readPoliciesFromXml(parser);
    300                 } else if ("password-quality".equals(tag)) {
    301                     passwordQuality = Integer.parseInt(
    302                             parser.getAttributeValue(null, "value"));
    303                 } else if ("min-password-length".equals(tag)) {
    304                     minimumPasswordLength = Integer.parseInt(
    305                             parser.getAttributeValue(null, "value"));
    306                 } else if ("password-history-length".equals(tag)) {
    307                     passwordHistoryLength = Integer.parseInt(
    308                             parser.getAttributeValue(null, "value"));
    309                 } else if ("min-password-uppercase".equals(tag)) {
    310                     minimumPasswordUpperCase = Integer.parseInt(
    311                             parser.getAttributeValue(null, "value"));
    312                 } else if ("min-password-lowercase".equals(tag)) {
    313                     minimumPasswordLowerCase = Integer.parseInt(
    314                             parser.getAttributeValue(null, "value"));
    315                 } else if ("min-password-letters".equals(tag)) {
    316                     minimumPasswordLetters = Integer.parseInt(
    317                             parser.getAttributeValue(null, "value"));
    318                 } else if ("min-password-numeric".equals(tag)) {
    319                     minimumPasswordNumeric = Integer.parseInt(
    320                             parser.getAttributeValue(null, "value"));
    321                 } else if ("min-password-symbols".equals(tag)) {
    322                     minimumPasswordSymbols = Integer.parseInt(
    323                             parser.getAttributeValue(null, "value"));
    324                 } else if ("min-password-nonletter".equals(tag)) {
    325                     minimumPasswordNonLetter = Integer.parseInt(
    326                             parser.getAttributeValue(null, "value"));
    327                 } else if ("max-time-to-unlock".equals(tag)) {
    328                     maximumTimeToUnlock = Long.parseLong(
    329                             parser.getAttributeValue(null, "value"));
    330                 } else if ("max-failed-password-wipe".equals(tag)) {
    331                     maximumFailedPasswordsForWipe = Integer.parseInt(
    332                             parser.getAttributeValue(null, "value"));
    333                 } else if ("specifies-global-proxy".equals(tag)) {
    334                     specifiesGlobalProxy = Boolean.parseBoolean(
    335                             parser.getAttributeValue(null, "value"));
    336                 } else if ("global-proxy-spec".equals(tag)) {
    337                     globalProxySpec =
    338                         parser.getAttributeValue(null, "value");
    339                 } else if ("global-proxy-exclusion-list".equals(tag)) {
    340                     globalProxyExclusionList =
    341                         parser.getAttributeValue(null, "value");
    342                 } else if ("password-expiration-timeout".equals(tag)) {
    343                     passwordExpirationTimeout = Long.parseLong(
    344                             parser.getAttributeValue(null, "value"));
    345                 } else if ("password-expiration-date".equals(tag)) {
    346                     passwordExpirationDate = Long.parseLong(
    347                             parser.getAttributeValue(null, "value"));
    348                 } else if ("encryption-requested".equals(tag)) {
    349                     encryptionRequested = Boolean.parseBoolean(
    350                             parser.getAttributeValue(null, "value"));
    351                 } else if ("disable-camera".equals(tag)) {
    352                     disableCamera = Boolean.parseBoolean(
    353                             parser.getAttributeValue(null, "value"));
    354                 } else {
    355                     Slog.w(TAG, "Unknown admin tag: " + tag);
    356                 }
    357                 XmlUtils.skipCurrentTag(parser);
    358             }
    359         }
    360 
    361         void dump(String prefix, PrintWriter pw) {
    362             pw.print(prefix); pw.print("uid="); pw.println(getUid());
    363             pw.print(prefix); pw.println("policies:");
    364             ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies();
    365             if (pols != null) {
    366                 for (int i=0; i<pols.size(); i++) {
    367                     pw.print(prefix); pw.print("  "); pw.println(pols.get(i).tag);
    368                 }
    369             }
    370             pw.print(prefix); pw.print("passwordQuality=0x");
    371                     pw.println(Integer.toHexString(passwordQuality));
    372             pw.print(prefix); pw.print("minimumPasswordLength=");
    373                     pw.println(minimumPasswordLength);
    374             pw.print(prefix); pw.print("passwordHistoryLength=");
    375                     pw.println(passwordHistoryLength);
    376             pw.print(prefix); pw.print("minimumPasswordUpperCase=");
    377                     pw.println(minimumPasswordUpperCase);
    378             pw.print(prefix); pw.print("minimumPasswordLowerCase=");
    379                     pw.println(minimumPasswordLowerCase);
    380             pw.print(prefix); pw.print("minimumPasswordLetters=");
    381                     pw.println(minimumPasswordLetters);
    382             pw.print(prefix); pw.print("minimumPasswordNumeric=");
    383                     pw.println(minimumPasswordNumeric);
    384             pw.print(prefix); pw.print("minimumPasswordSymbols=");
    385                     pw.println(minimumPasswordSymbols);
    386             pw.print(prefix); pw.print("minimumPasswordNonLetter=");
    387                     pw.println(minimumPasswordNonLetter);
    388             pw.print(prefix); pw.print("maximumTimeToUnlock=");
    389                     pw.println(maximumTimeToUnlock);
    390             pw.print(prefix); pw.print("maximumFailedPasswordsForWipe=");
    391                     pw.println(maximumFailedPasswordsForWipe);
    392             pw.print(prefix); pw.print("specifiesGlobalProxy=");
    393                     pw.println(specifiesGlobalProxy);
    394             pw.print(prefix); pw.print("passwordExpirationTimeout=");
    395                     pw.println(passwordExpirationTimeout);
    396             pw.print(prefix); pw.print("passwordExpirationDate=");
    397                     pw.println(passwordExpirationDate);
    398             if (globalProxySpec != null) {
    399                 pw.print(prefix); pw.print("globalProxySpec=");
    400                         pw.println(globalProxySpec);
    401             }
    402             if (globalProxyExclusionList != null) {
    403                 pw.print(prefix); pw.print("globalProxyEclusionList=");
    404                         pw.println(globalProxyExclusionList);
    405             }
    406             pw.print(prefix); pw.print("encryptionRequested=");
    407                     pw.println(encryptionRequested);
    408             pw.print(prefix); pw.print("disableCamera=");
    409                     pw.println(disableCamera);
    410         }
    411     }
    412 
    413     class MyPackageMonitor extends PackageMonitor {
    414         @Override
    415         public void onSomePackagesChanged() {
    416             synchronized (DevicePolicyManagerService.this) {
    417                 boolean removed = false;
    418                 for (int i=mAdminList.size()-1; i>=0; i--) {
    419                     ActiveAdmin aa = mAdminList.get(i);
    420                     int change = isPackageDisappearing(aa.info.getPackageName());
    421                     if (change == PACKAGE_PERMANENT_CHANGE
    422                             || change == PACKAGE_TEMPORARY_CHANGE) {
    423                         Slog.w(TAG, "Admin unexpectedly uninstalled: "
    424                                 + aa.info.getComponent());
    425                         removed = true;
    426                         mAdminList.remove(i);
    427                     } else if (isPackageModified(aa.info.getPackageName())) {
    428                         try {
    429                             mContext.getPackageManager().getReceiverInfo(
    430                                     aa.info.getComponent(), 0);
    431                         } catch (NameNotFoundException e) {
    432                             Slog.w(TAG, "Admin package change removed component: "
    433                                     + aa.info.getComponent());
    434                             removed = true;
    435                             mAdminList.remove(i);
    436                         }
    437                     }
    438                 }
    439                 if (removed) {
    440                     validatePasswordOwnerLocked();
    441                     syncDeviceCapabilitiesLocked();
    442                     saveSettingsLocked();
    443                 }
    444             }
    445         }
    446     }
    447 
    448     /**
    449      * Instantiates the service.
    450      */
    451     public DevicePolicyManagerService(Context context) {
    452         mContext = context;
    453         mMonitor = new MyPackageMonitor();
    454         mMonitor.register(context, true);
    455         mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE))
    456                 .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM");
    457         IntentFilter filter = new IntentFilter();
    458         filter.addAction(Intent.ACTION_BOOT_COMPLETED);
    459         filter.addAction(ACTION_EXPIRED_PASSWORD_NOTIFICATION);
    460         context.registerReceiver(mReceiver, filter);
    461     }
    462 
    463     /**
    464      * Set an alarm for an upcoming event - expiration warning, expiration, or post-expiration
    465      * reminders.  Clears alarm if no expirations are configured.
    466      */
    467     protected void setExpirationAlarmCheckLocked(Context context) {
    468         final long expiration = getPasswordExpirationLocked(null);
    469         final long now = System.currentTimeMillis();
    470         final long timeToExpire = expiration - now;
    471         final long alarmTime;
    472         if (expiration == 0) {
    473             // No expirations are currently configured:  Cancel alarm.
    474             alarmTime = 0;
    475         } else if (timeToExpire <= 0) {
    476             // The password has already expired:  Repeat every 24 hours.
    477             alarmTime = now + MS_PER_DAY;
    478         } else {
    479             // Selecting the next alarm time:  Roll forward to the next 24 hour multiple before
    480             // the expiration time.
    481             long alarmInterval = timeToExpire % MS_PER_DAY;
    482             if (alarmInterval == 0) {
    483                 alarmInterval = MS_PER_DAY;
    484             }
    485             alarmTime = now + alarmInterval;
    486         }
    487 
    488         long token = Binder.clearCallingIdentity();
    489         try {
    490             AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    491             PendingIntent pi = PendingIntent.getBroadcast(context, REQUEST_EXPIRE_PASSWORD,
    492                     new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION),
    493                     PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
    494             am.cancel(pi);
    495             if (alarmTime != 0) {
    496                 am.set(AlarmManager.RTC, alarmTime, pi);
    497             }
    498         } finally {
    499             Binder.restoreCallingIdentity(token);
    500         }
    501     }
    502 
    503     private IPowerManager getIPowerManager() {
    504         if (mIPowerManager == null) {
    505             IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
    506             mIPowerManager = IPowerManager.Stub.asInterface(b);
    507         }
    508         return mIPowerManager;
    509     }
    510 
    511     private IWindowManager getWindowManager() {
    512         if (mIWindowManager == null) {
    513             IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE);
    514             mIWindowManager = IWindowManager.Stub.asInterface(b);
    515         }
    516         return mIWindowManager;
    517     }
    518 
    519     ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) {
    520         ActiveAdmin admin = mAdminMap.get(who);
    521         if (admin != null
    522                 && who.getPackageName().equals(admin.info.getActivityInfo().packageName)
    523                 && who.getClassName().equals(admin.info.getActivityInfo().name)) {
    524             return admin;
    525         }
    526         return null;
    527     }
    528 
    529     ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
    530             throws SecurityException {
    531         final int callingUid = Binder.getCallingUid();
    532         if (who != null) {
    533             ActiveAdmin admin = mAdminMap.get(who);
    534             if (admin == null) {
    535                 throw new SecurityException("No active admin " + who);
    536             }
    537             if (admin.getUid() != callingUid) {
    538                 throw new SecurityException("Admin " + who + " is not owned by uid "
    539                         + Binder.getCallingUid());
    540             }
    541             if (!admin.info.usesPolicy(reqPolicy)) {
    542                 throw new SecurityException("Admin " + admin.info.getComponent()
    543                         + " did not specify uses-policy for: "
    544                         + admin.info.getTagForPolicy(reqPolicy));
    545             }
    546             return admin;
    547         } else {
    548             final int N = mAdminList.size();
    549             for (int i=0; i<N; i++) {
    550                 ActiveAdmin admin = mAdminList.get(i);
    551                 if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) {
    552                     return admin;
    553                 }
    554             }
    555             throw new SecurityException("No active admin owned by uid "
    556                     + Binder.getCallingUid() + " for policy #" + reqPolicy);
    557         }
    558     }
    559 
    560     void sendAdminCommandLocked(ActiveAdmin admin, String action) {
    561         sendAdminCommandLocked(admin, action, null);
    562     }
    563 
    564     void sendAdminCommandLocked(ActiveAdmin admin, String action, BroadcastReceiver result) {
    565         Intent intent = new Intent(action);
    566         intent.setComponent(admin.info.getComponent());
    567         if (action.equals(DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING)) {
    568             intent.putExtra("expiration", admin.passwordExpirationDate);
    569         }
    570         if (result != null) {
    571             mContext.sendOrderedBroadcast(intent, null, result, mHandler,
    572                     Activity.RESULT_OK, null, null);
    573         } else {
    574             mContext.sendBroadcast(intent);
    575         }
    576     }
    577 
    578     void sendAdminCommandLocked(String action, int reqPolicy) {
    579         final int N = mAdminList.size();
    580         if (N > 0) {
    581             for (int i=0; i<N; i++) {
    582                 ActiveAdmin admin = mAdminList.get(i);
    583                 if (admin.info.usesPolicy(reqPolicy)) {
    584                     sendAdminCommandLocked(admin, action);
    585                 }
    586             }
    587         }
    588     }
    589 
    590     void removeActiveAdminLocked(final ComponentName adminReceiver) {
    591         final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
    592         if (admin != null) {
    593             sendAdminCommandLocked(admin,
    594                     DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED,
    595                     new BroadcastReceiver() {
    596                         @Override
    597                         public void onReceive(Context context, Intent intent) {
    598                             synchronized (this) {
    599                                 boolean doProxyCleanup = admin.info.usesPolicy(
    600                                         DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
    601                                 mAdminList.remove(admin);
    602                                 mAdminMap.remove(adminReceiver);
    603                                 validatePasswordOwnerLocked();
    604                                 syncDeviceCapabilitiesLocked();
    605                                 if (doProxyCleanup) {
    606                                     resetGlobalProxy();
    607                                 }
    608                                 saveSettingsLocked();
    609                             }
    610                         }
    611             });
    612         }
    613     }
    614 
    615     public DeviceAdminInfo findAdmin(ComponentName adminName) {
    616         Intent resolveIntent = new Intent();
    617         resolveIntent.setComponent(adminName);
    618         List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceivers(
    619                 resolveIntent, PackageManager.GET_META_DATA);
    620         if (infos == null || infos.size() <= 0) {
    621             throw new IllegalArgumentException("Unknown admin: " + adminName);
    622         }
    623 
    624         try {
    625             return new DeviceAdminInfo(mContext, infos.get(0));
    626         } catch (XmlPullParserException e) {
    627             Slog.w(TAG, "Bad device admin requested: " + adminName, e);
    628             return null;
    629         } catch (IOException e) {
    630             Slog.w(TAG, "Bad device admin requested: " + adminName, e);
    631             return null;
    632         }
    633     }
    634 
    635     private static JournaledFile makeJournaledFile() {
    636         final String base = "/data/system/device_policies.xml";
    637         return new JournaledFile(new File(base), new File(base + ".tmp"));
    638     }
    639 
    640     private void saveSettingsLocked() {
    641         JournaledFile journal = makeJournaledFile();
    642         FileOutputStream stream = null;
    643         try {
    644             stream = new FileOutputStream(journal.chooseForWrite(), false);
    645             XmlSerializer out = new FastXmlSerializer();
    646             out.setOutput(stream, "utf-8");
    647             out.startDocument(null, true);
    648 
    649             out.startTag(null, "policies");
    650 
    651             final int N = mAdminList.size();
    652             for (int i=0; i<N; i++) {
    653                 ActiveAdmin ap = mAdminList.get(i);
    654                 if (ap != null) {
    655                     out.startTag(null, "admin");
    656                     out.attribute(null, "name", ap.info.getComponent().flattenToString());
    657                     ap.writeToXml(out);
    658                     out.endTag(null, "admin");
    659                 }
    660             }
    661 
    662             if (mPasswordOwner >= 0) {
    663                 out.startTag(null, "password-owner");
    664                 out.attribute(null, "value", Integer.toString(mPasswordOwner));
    665                 out.endTag(null, "password-owner");
    666             }
    667 
    668             if (mFailedPasswordAttempts != 0) {
    669                 out.startTag(null, "failed-password-attempts");
    670                 out.attribute(null, "value", Integer.toString(mFailedPasswordAttempts));
    671                 out.endTag(null, "failed-password-attempts");
    672             }
    673 
    674             if (mActivePasswordQuality != 0 || mActivePasswordLength != 0
    675                     || mActivePasswordUpperCase != 0 || mActivePasswordLowerCase != 0
    676                     || mActivePasswordLetters != 0 || mActivePasswordNumeric != 0
    677                     || mActivePasswordSymbols != 0 || mActivePasswordNonLetter != 0) {
    678                 out.startTag(null, "active-password");
    679                 out.attribute(null, "quality", Integer.toString(mActivePasswordQuality));
    680                 out.attribute(null, "length", Integer.toString(mActivePasswordLength));
    681                 out.attribute(null, "uppercase", Integer.toString(mActivePasswordUpperCase));
    682                 out.attribute(null, "lowercase", Integer.toString(mActivePasswordLowerCase));
    683                 out.attribute(null, "letters", Integer.toString(mActivePasswordLetters));
    684                 out.attribute(null, "numeric", Integer
    685                         .toString(mActivePasswordNumeric));
    686                 out.attribute(null, "symbols", Integer.toString(mActivePasswordSymbols));
    687                 out.attribute(null, "nonletter", Integer.toString(mActivePasswordNonLetter));
    688                 out.endTag(null, "active-password");
    689             }
    690 
    691             out.endTag(null, "policies");
    692 
    693             out.endDocument();
    694             stream.close();
    695             journal.commit();
    696             sendChangedNotification();
    697         } catch (IOException e) {
    698             try {
    699                 if (stream != null) {
    700                     stream.close();
    701                 }
    702             } catch (IOException ex) {
    703                 // Ignore
    704             }
    705             journal.rollback();
    706         }
    707     }
    708 
    709     private void sendChangedNotification() {
    710         Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
    711         intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
    712         mContext.sendBroadcast(intent);
    713     }
    714 
    715     private void loadSettingsLocked() {
    716         JournaledFile journal = makeJournaledFile();
    717         FileInputStream stream = null;
    718         File file = journal.chooseForRead();
    719         try {
    720             stream = new FileInputStream(file);
    721             XmlPullParser parser = Xml.newPullParser();
    722             parser.setInput(stream, null);
    723 
    724             int type;
    725             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
    726                     && type != XmlPullParser.START_TAG) {
    727             }
    728             String tag = parser.getName();
    729             if (!"policies".equals(tag)) {
    730                 throw new XmlPullParserException(
    731                         "Settings do not start with policies tag: found " + tag);
    732             }
    733             type = parser.next();
    734             int outerDepth = parser.getDepth();
    735             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
    736                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
    737                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
    738                     continue;
    739                 }
    740                 tag = parser.getName();
    741                 if ("admin".equals(tag)) {
    742                     String name = parser.getAttributeValue(null, "name");
    743                     try {
    744                         DeviceAdminInfo dai = findAdmin(
    745                                 ComponentName.unflattenFromString(name));
    746                         if (dai != null) {
    747                             ActiveAdmin ap = new ActiveAdmin(dai);
    748                             ap.readFromXml(parser);
    749                             mAdminMap.put(ap.info.getComponent(), ap);
    750                             mAdminList.add(ap);
    751                         }
    752                     } catch (RuntimeException e) {
    753                         Slog.w(TAG, "Failed loading admin " + name, e);
    754                     }
    755                 } else if ("failed-password-attempts".equals(tag)) {
    756                     mFailedPasswordAttempts = Integer.parseInt(
    757                             parser.getAttributeValue(null, "value"));
    758                     XmlUtils.skipCurrentTag(parser);
    759                 } else if ("password-owner".equals(tag)) {
    760                     mPasswordOwner = Integer.parseInt(
    761                             parser.getAttributeValue(null, "value"));
    762                     XmlUtils.skipCurrentTag(parser);
    763                 } else if ("active-password".equals(tag)) {
    764                     mActivePasswordQuality = Integer.parseInt(
    765                             parser.getAttributeValue(null, "quality"));
    766                     mActivePasswordLength = Integer.parseInt(
    767                             parser.getAttributeValue(null, "length"));
    768                     mActivePasswordUpperCase = Integer.parseInt(
    769                             parser.getAttributeValue(null, "uppercase"));
    770                     mActivePasswordLowerCase = Integer.parseInt(
    771                             parser.getAttributeValue(null, "lowercase"));
    772                     mActivePasswordLetters = Integer.parseInt(
    773                             parser.getAttributeValue(null, "letters"));
    774                     mActivePasswordNumeric = Integer.parseInt(
    775                             parser.getAttributeValue(null, "numeric"));
    776                     mActivePasswordSymbols = Integer.parseInt(
    777                             parser.getAttributeValue(null, "symbols"));
    778                     mActivePasswordNonLetter = Integer.parseInt(
    779                             parser.getAttributeValue(null, "nonletter"));
    780                     XmlUtils.skipCurrentTag(parser);
    781                 } else {
    782                     Slog.w(TAG, "Unknown tag: " + tag);
    783                     XmlUtils.skipCurrentTag(parser);
    784                 }
    785             }
    786         } catch (NullPointerException e) {
    787             Slog.w(TAG, "failed parsing " + file + " " + e);
    788         } catch (NumberFormatException e) {
    789             Slog.w(TAG, "failed parsing " + file + " " + e);
    790         } catch (XmlPullParserException e) {
    791             Slog.w(TAG, "failed parsing " + file + " " + e);
    792         } catch (FileNotFoundException e) {
    793             // Don't be noisy, this is normal if we haven't defined any policies.
    794         } catch (IOException e) {
    795             Slog.w(TAG, "failed parsing " + file + " " + e);
    796         } catch (IndexOutOfBoundsException e) {
    797             Slog.w(TAG, "failed parsing " + file + " " + e);
    798         }
    799         try {
    800             if (stream != null) {
    801                 stream.close();
    802             }
    803         } catch (IOException e) {
    804             // Ignore
    805         }
    806 
    807         // Validate that what we stored for the password quality matches
    808         // sufficiently what is currently set.  Note that this is only
    809         // a sanity check in case the two get out of sync; this should
    810         // never normally happen.
    811         LockPatternUtils utils = new LockPatternUtils(mContext);
    812         if (utils.getActivePasswordQuality() < mActivePasswordQuality) {
    813             Slog.w(TAG, "Active password quality 0x"
    814                     + Integer.toHexString(mActivePasswordQuality)
    815                     + " does not match actual quality 0x"
    816                     + Integer.toHexString(utils.getActivePasswordQuality()));
    817             mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
    818             mActivePasswordLength = 0;
    819             mActivePasswordUpperCase = 0;
    820             mActivePasswordLowerCase = 0;
    821             mActivePasswordLetters = 0;
    822             mActivePasswordNumeric = 0;
    823             mActivePasswordSymbols = 0;
    824             mActivePasswordNonLetter = 0;
    825         }
    826 
    827         validatePasswordOwnerLocked();
    828         syncDeviceCapabilitiesLocked();
    829 
    830         long timeMs = getMaximumTimeToLock(null);
    831         if (timeMs <= 0) {
    832             timeMs = Integer.MAX_VALUE;
    833         }
    834         try {
    835             getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
    836         } catch (RemoteException e) {
    837             Slog.w(TAG, "Failure talking with power manager", e);
    838         }
    839     }
    840 
    841     static void validateQualityConstant(int quality) {
    842         switch (quality) {
    843             case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
    844             case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK:
    845             case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
    846             case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
    847             case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
    848             case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
    849             case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
    850                 return;
    851         }
    852         throw new IllegalArgumentException("Invalid quality constant: 0x"
    853                 + Integer.toHexString(quality));
    854     }
    855 
    856     void validatePasswordOwnerLocked() {
    857         if (mPasswordOwner >= 0) {
    858             boolean haveOwner = false;
    859             for (int i=mAdminList.size()-1; i>=0; i--) {
    860                 if (mAdminList.get(i).getUid() == mPasswordOwner) {
    861                     haveOwner = true;
    862                     break;
    863                 }
    864             }
    865             if (!haveOwner) {
    866                 Slog.w(TAG, "Previous password owner " + mPasswordOwner
    867                         + " no longer active; disabling");
    868                 mPasswordOwner = -1;
    869             }
    870         }
    871     }
    872 
    873     /**
    874      * Pushes down policy information to the system for any policies related to general device
    875      * capabilities that need to be enforced by lower level services (e.g. Camera services).
    876      */
    877     void syncDeviceCapabilitiesLocked() {
    878         // Ensure the status of the camera is synced down to the system. Interested native services
    879         // should monitor this value and act accordingly.
    880         boolean systemState = SystemProperties.getBoolean(SYSTEM_PROP_DISABLE_CAMERA, false);
    881         boolean cameraDisabled = getCameraDisabled(null);
    882         if (cameraDisabled != systemState) {
    883             long token = Binder.clearCallingIdentity();
    884             try {
    885                 String value = cameraDisabled ? "1" : "0";
    886                 Slog.v(TAG, "Change in camera state ["
    887                         + SYSTEM_PROP_DISABLE_CAMERA + "] = " + value);
    888                 SystemProperties.set(SYSTEM_PROP_DISABLE_CAMERA, value);
    889             } finally {
    890                 Binder.restoreCallingIdentity(token);
    891             }
    892         }
    893     }
    894 
    895     public void systemReady() {
    896         synchronized (this) {
    897             loadSettingsLocked();
    898         }
    899     }
    900 
    901     private void handlePasswordExpirationNotification() {
    902         synchronized (this) {
    903             final long now = System.currentTimeMillis();
    904             final int N = mAdminList.size();
    905             if (N <= 0) {
    906                 return;
    907             }
    908             for (int i=0; i < N; i++) {
    909                 ActiveAdmin admin = mAdminList.get(i);
    910                 if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)
    911                         && admin.passwordExpirationTimeout > 0L
    912                         && admin.passwordExpirationDate > 0L
    913                         && now >= admin.passwordExpirationDate - EXPIRATION_GRACE_PERIOD_MS) {
    914                     sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING);
    915                 }
    916             }
    917             setExpirationAlarmCheckLocked(mContext);
    918         }
    919     }
    920 
    921     /**
    922      * @param adminReceiver The admin to add
    923      * @param refreshing true = update an active admin, no error
    924      */
    925     public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing) {
    926         mContext.enforceCallingOrSelfPermission(
    927                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
    928 
    929         DeviceAdminInfo info = findAdmin(adminReceiver);
    930         if (info == null) {
    931             throw new IllegalArgumentException("Bad admin: " + adminReceiver);
    932         }
    933         synchronized (this) {
    934             long ident = Binder.clearCallingIdentity();
    935             try {
    936                 if (!refreshing && getActiveAdminUncheckedLocked(adminReceiver) != null) {
    937                     throw new IllegalArgumentException("Admin is already added");
    938                 }
    939                 ActiveAdmin newAdmin = new ActiveAdmin(info);
    940                 mAdminMap.put(adminReceiver, newAdmin);
    941                 int replaceIndex = -1;
    942                 if (refreshing) {
    943                     final int N = mAdminList.size();
    944                     for (int i=0; i < N; i++) {
    945                         ActiveAdmin oldAdmin = mAdminList.get(i);
    946                         if (oldAdmin.info.getComponent().equals(adminReceiver)) {
    947                             replaceIndex = i;
    948                             break;
    949                         }
    950                     }
    951                 }
    952                 if (replaceIndex == -1) {
    953                     mAdminList.add(newAdmin);
    954                 } else {
    955                     mAdminList.set(replaceIndex, newAdmin);
    956                 }
    957                 saveSettingsLocked();
    958                 sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED);
    959             } finally {
    960                 Binder.restoreCallingIdentity(ident);
    961             }
    962         }
    963     }
    964 
    965     public boolean isAdminActive(ComponentName adminReceiver) {
    966         synchronized (this) {
    967             return getActiveAdminUncheckedLocked(adminReceiver) != null;
    968         }
    969     }
    970 
    971     public boolean hasGrantedPolicy(ComponentName adminReceiver, int policyId) {
    972         synchronized (this) {
    973             ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver);
    974             if (administrator == null) {
    975                 throw new SecurityException("No active admin " + adminReceiver);
    976             }
    977             return administrator.info.usesPolicy(policyId);
    978         }
    979     }
    980 
    981     public List<ComponentName> getActiveAdmins() {
    982         synchronized (this) {
    983             final int N = mAdminList.size();
    984             if (N <= 0) {
    985                 return null;
    986             }
    987             ArrayList<ComponentName> res = new ArrayList<ComponentName>(N);
    988             for (int i=0; i<N; i++) {
    989                 res.add(mAdminList.get(i).info.getComponent());
    990             }
    991             return res;
    992         }
    993     }
    994 
    995     public boolean packageHasActiveAdmins(String packageName) {
    996         synchronized (this) {
    997             final int N = mAdminList.size();
    998             for (int i=0; i<N; i++) {
    999                 if (mAdminList.get(i).info.getPackageName().equals(packageName)) {
   1000                     return true;
   1001                 }
   1002             }
   1003             return false;
   1004         }
   1005     }
   1006 
   1007     public void removeActiveAdmin(ComponentName adminReceiver) {
   1008         synchronized (this) {
   1009             ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
   1010             if (admin == null) {
   1011                 return;
   1012             }
   1013             if (admin.getUid() != Binder.getCallingUid()) {
   1014                 mContext.enforceCallingOrSelfPermission(
   1015                         android.Manifest.permission.BIND_DEVICE_ADMIN, null);
   1016             }
   1017             long ident = Binder.clearCallingIdentity();
   1018             try {
   1019                 removeActiveAdminLocked(adminReceiver);
   1020             } finally {
   1021                 Binder.restoreCallingIdentity(ident);
   1022             }
   1023         }
   1024     }
   1025 
   1026     public void setPasswordQuality(ComponentName who, int quality) {
   1027         validateQualityConstant(quality);
   1028 
   1029         synchronized (this) {
   1030             if (who == null) {
   1031                 throw new NullPointerException("ComponentName is null");
   1032             }
   1033             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
   1034                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
   1035             if (ap.passwordQuality != quality) {
   1036                 ap.passwordQuality = quality;
   1037                 saveSettingsLocked();
   1038             }
   1039         }
   1040     }
   1041 
   1042     public int getPasswordQuality(ComponentName who) {
   1043         synchronized (this) {
   1044             int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
   1045 
   1046             if (who != null) {
   1047                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
   1048                 return admin != null ? admin.passwordQuality : mode;
   1049             }
   1050 
   1051             final int N = mAdminList.size();
   1052             for  (int i=0; i<N; i++) {
   1053                 ActiveAdmin admin = mAdminList.get(i);
   1054                 if (mode < admin.passwordQuality) {
   1055                     mode = admin.passwordQuality;
   1056                 }
   1057             }
   1058             return mode;
   1059         }
   1060     }
   1061 
   1062     public void setPasswordMinimumLength(ComponentName who, int length) {
   1063         synchronized (this) {
   1064             if (who == null) {
   1065                 throw new NullPointerException("ComponentName is null");
   1066             }
   1067             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
   1068                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
   1069             if (ap.minimumPasswordLength != length) {
   1070                 ap.minimumPasswordLength = length;
   1071                 saveSettingsLocked();
   1072             }
   1073         }
   1074     }
   1075 
   1076     public int getPasswordMinimumLength(ComponentName who) {
   1077         synchronized (this) {
   1078             int length = 0;
   1079 
   1080             if (who != null) {
   1081                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
   1082                 return admin != null ? admin.minimumPasswordLength : length;
   1083             }
   1084 
   1085             final int N = mAdminList.size();
   1086             for  (int i=0; i<N; i++) {
   1087                 ActiveAdmin admin = mAdminList.get(i);
   1088                 if (length < admin.minimumPasswordLength) {
   1089                     length = admin.minimumPasswordLength;
   1090                 }
   1091             }
   1092             return length;
   1093         }
   1094     }
   1095 
   1096     public void setPasswordHistoryLength(ComponentName who, int length) {
   1097         synchronized (this) {
   1098             if (who == null) {
   1099                 throw new NullPointerException("ComponentName is null");
   1100             }
   1101             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
   1102                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
   1103             if (ap.passwordHistoryLength != length) {
   1104                 ap.passwordHistoryLength = length;
   1105                 saveSettingsLocked();
   1106             }
   1107         }
   1108     }
   1109 
   1110     public int getPasswordHistoryLength(ComponentName who) {
   1111         synchronized (this) {
   1112             int length = 0;
   1113 
   1114             if (who != null) {
   1115                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
   1116                 return admin != null ? admin.passwordHistoryLength : length;
   1117             }
   1118 
   1119             final int N = mAdminList.size();
   1120             for (int i = 0; i < N; i++) {
   1121                 ActiveAdmin admin = mAdminList.get(i);
   1122                 if (length < admin.passwordHistoryLength) {
   1123                     length = admin.passwordHistoryLength;
   1124                 }
   1125             }
   1126             return length;
   1127         }
   1128     }
   1129 
   1130     public void setPasswordExpirationTimeout(ComponentName who, long timeout) {
   1131         synchronized (this) {
   1132             if (who == null) {
   1133                 throw new NullPointerException("ComponentName is null");
   1134             }
   1135             if (timeout < 0) {
   1136                 throw new IllegalArgumentException("Timeout must be >= 0 ms");
   1137             }
   1138             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
   1139                     DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD);
   1140             // Calling this API automatically bumps the expiration date
   1141             final long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L;
   1142             ap.passwordExpirationDate = expiration;
   1143             ap.passwordExpirationTimeout = timeout;
   1144             if (timeout > 0L) {
   1145                 Slog.w(TAG, "setPasswordExpiration(): password will expire on "
   1146                         + DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)
   1147                         .format(new Date(expiration)));
   1148             }
   1149             saveSettingsLocked();
   1150             setExpirationAlarmCheckLocked(mContext); // in case this is the first one
   1151         }
   1152     }
   1153 
   1154     /**
   1155      * Return a single admin's expiration cycle time, or the min of all cycle times.
   1156      * Returns 0 if not configured.
   1157      */
   1158     public long getPasswordExpirationTimeout(ComponentName who) {
   1159         synchronized (this) {
   1160             if (who != null) {
   1161                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
   1162                 return admin != null ? admin.passwordExpirationTimeout : 0L;
   1163             }
   1164 
   1165             long timeout = 0L;
   1166             final int N = mAdminList.size();
   1167             for (int i = 0; i < N; i++) {
   1168                 ActiveAdmin admin = mAdminList.get(i);
   1169                 if (timeout == 0L || (admin.passwordExpirationTimeout != 0L
   1170                         && timeout > admin.passwordExpirationTimeout)) {
   1171                     timeout = admin.passwordExpirationTimeout;
   1172                 }
   1173             }
   1174             return timeout;
   1175         }
   1176     }
   1177 
   1178     /**
   1179      * Return a single admin's expiration date/time, or the min (soonest) for all admins.
   1180      * Returns 0 if not configured.
   1181      */
   1182     private long getPasswordExpirationLocked(ComponentName who) {
   1183         if (who != null) {
   1184             ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
   1185             return admin != null ? admin.passwordExpirationDate : 0L;
   1186         }
   1187 
   1188         long timeout = 0L;
   1189         final int N = mAdminList.size();
   1190         for (int i = 0; i < N; i++) {
   1191             ActiveAdmin admin = mAdminList.get(i);
   1192             if (timeout == 0L || (admin.passwordExpirationDate != 0
   1193                     && timeout > admin.passwordExpirationDate)) {
   1194                 timeout = admin.passwordExpirationDate;
   1195             }
   1196         }
   1197         return timeout;
   1198     }
   1199 
   1200     public long getPasswordExpiration(ComponentName who) {
   1201         synchronized (this) {
   1202             return getPasswordExpirationLocked(who);
   1203         }
   1204     }
   1205 
   1206     public void setPasswordMinimumUpperCase(ComponentName who, int length) {
   1207         synchronized (this) {
   1208             if (who == null) {
   1209                 throw new NullPointerException("ComponentName is null");
   1210             }
   1211             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
   1212                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
   1213             if (ap.minimumPasswordUpperCase != length) {
   1214                 ap.minimumPasswordUpperCase = length;
   1215                 saveSettingsLocked();
   1216             }
   1217         }
   1218     }
   1219 
   1220     public int getPasswordMinimumUpperCase(ComponentName who) {
   1221         synchronized (this) {
   1222             int length = 0;
   1223 
   1224             if (who != null) {
   1225                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
   1226                 return admin != null ? admin.minimumPasswordUpperCase : length;
   1227             }
   1228 
   1229             final int N = mAdminList.size();
   1230             for (int i=0; i<N; i++) {
   1231                 ActiveAdmin admin = mAdminList.get(i);
   1232                 if (length < admin.minimumPasswordUpperCase) {
   1233                     length = admin.minimumPasswordUpperCase;
   1234                 }
   1235             }
   1236             return length;
   1237         }
   1238     }
   1239 
   1240     public void setPasswordMinimumLowerCase(ComponentName who, int length) {
   1241         synchronized (this) {
   1242             if (who == null) {
   1243                 throw new NullPointerException("ComponentName is null");
   1244             }
   1245             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
   1246                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
   1247             if (ap.minimumPasswordLowerCase != length) {
   1248                 ap.minimumPasswordLowerCase = length;
   1249                 saveSettingsLocked();
   1250             }
   1251         }
   1252     }
   1253 
   1254     public int getPasswordMinimumLowerCase(ComponentName who) {
   1255         synchronized (this) {
   1256             int length = 0;
   1257 
   1258             if (who != null) {
   1259                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
   1260                 return admin != null ? admin.minimumPasswordLowerCase : length;
   1261             }
   1262 
   1263             final int N = mAdminList.size();
   1264             for (int i=0; i<N; i++) {
   1265                 ActiveAdmin admin = mAdminList.get(i);
   1266                 if (length < admin.minimumPasswordLowerCase) {
   1267                     length = admin.minimumPasswordLowerCase;
   1268                 }
   1269             }
   1270             return length;
   1271         }
   1272     }
   1273 
   1274     public void setPasswordMinimumLetters(ComponentName who, int length) {
   1275         synchronized (this) {
   1276             if (who == null) {
   1277                 throw new NullPointerException("ComponentName is null");
   1278             }
   1279             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
   1280                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
   1281             if (ap.minimumPasswordLetters != length) {
   1282                 ap.minimumPasswordLetters = length;
   1283                 saveSettingsLocked();
   1284             }
   1285         }
   1286     }
   1287 
   1288     public int getPasswordMinimumLetters(ComponentName who) {
   1289         synchronized (this) {
   1290             int length = 0;
   1291 
   1292             if (who != null) {
   1293                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
   1294                 return admin != null ? admin.minimumPasswordLetters : length;
   1295             }
   1296 
   1297             final int N = mAdminList.size();
   1298             for (int i=0; i<N; i++) {
   1299                 ActiveAdmin admin = mAdminList.get(i);
   1300                 if (length < admin.minimumPasswordLetters) {
   1301                     length = admin.minimumPasswordLetters;
   1302                 }
   1303             }
   1304             return length;
   1305         }
   1306     }
   1307 
   1308     public void setPasswordMinimumNumeric(ComponentName who, int length) {
   1309         synchronized (this) {
   1310             if (who == null) {
   1311                 throw new NullPointerException("ComponentName is null");
   1312             }
   1313             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
   1314                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
   1315             if (ap.minimumPasswordNumeric != length) {
   1316                 ap.minimumPasswordNumeric = length;
   1317                 saveSettingsLocked();
   1318             }
   1319         }
   1320     }
   1321 
   1322     public int getPasswordMinimumNumeric(ComponentName who) {
   1323         synchronized (this) {
   1324             int length = 0;
   1325 
   1326             if (who != null) {
   1327                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
   1328                 return admin != null ? admin.minimumPasswordNumeric : length;
   1329             }
   1330 
   1331             final int N = mAdminList.size();
   1332             for (int i = 0; i < N; i++) {
   1333                 ActiveAdmin admin = mAdminList.get(i);
   1334                 if (length < admin.minimumPasswordNumeric) {
   1335                     length = admin.minimumPasswordNumeric;
   1336                 }
   1337             }
   1338             return length;
   1339         }
   1340     }
   1341 
   1342     public void setPasswordMinimumSymbols(ComponentName who, int length) {
   1343         synchronized (this) {
   1344             if (who == null) {
   1345                 throw new NullPointerException("ComponentName is null");
   1346             }
   1347             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
   1348                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
   1349             if (ap.minimumPasswordSymbols != length) {
   1350                 ap.minimumPasswordSymbols = length;
   1351                 saveSettingsLocked();
   1352             }
   1353         }
   1354     }
   1355 
   1356     public int getPasswordMinimumSymbols(ComponentName who) {
   1357         synchronized (this) {
   1358             int length = 0;
   1359 
   1360             if (who != null) {
   1361                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
   1362                 return admin != null ? admin.minimumPasswordSymbols : length;
   1363             }
   1364 
   1365             final int N = mAdminList.size();
   1366             for  (int i=0; i<N; i++) {
   1367                 ActiveAdmin admin = mAdminList.get(i);
   1368                 if (length < admin.minimumPasswordSymbols) {
   1369                     length = admin.minimumPasswordSymbols;
   1370                 }
   1371             }
   1372             return length;
   1373         }
   1374     }
   1375 
   1376     public void setPasswordMinimumNonLetter(ComponentName who, int length) {
   1377         synchronized (this) {
   1378             if (who == null) {
   1379                 throw new NullPointerException("ComponentName is null");
   1380             }
   1381             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
   1382                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
   1383             if (ap.minimumPasswordNonLetter != length) {
   1384                 ap.minimumPasswordNonLetter = length;
   1385                 saveSettingsLocked();
   1386             }
   1387         }
   1388     }
   1389 
   1390     public int getPasswordMinimumNonLetter(ComponentName who) {
   1391         synchronized (this) {
   1392             int length = 0;
   1393 
   1394             if (who != null) {
   1395                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
   1396                 return admin != null ? admin.minimumPasswordNonLetter : length;
   1397             }
   1398 
   1399             final int N = mAdminList.size();
   1400             for (int i=0; i<N; i++) {
   1401                 ActiveAdmin admin = mAdminList.get(i);
   1402                 if (length < admin.minimumPasswordNonLetter) {
   1403                     length = admin.minimumPasswordNonLetter;
   1404                 }
   1405             }
   1406             return length;
   1407         }
   1408     }
   1409 
   1410     public boolean isActivePasswordSufficient() {
   1411         synchronized (this) {
   1412             // This API can only be called by an active device admin,
   1413             // so try to retrieve it to check that the caller is one.
   1414             getActiveAdminForCallerLocked(null,
   1415                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
   1416             if (mActivePasswordQuality < getPasswordQuality(null)
   1417                     || mActivePasswordLength < getPasswordMinimumLength(null)) {
   1418                 return false;
   1419             }
   1420             if(mActivePasswordQuality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
   1421                 return true;
   1422             }
   1423             return mActivePasswordUpperCase >= getPasswordMinimumUpperCase(null)
   1424                     && mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null)
   1425                     && mActivePasswordLetters >= getPasswordMinimumLetters(null)
   1426                     && mActivePasswordNumeric >= getPasswordMinimumNumeric(null)
   1427                     && mActivePasswordSymbols >= getPasswordMinimumSymbols(null)
   1428                     && mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null);
   1429         }
   1430     }
   1431 
   1432     public int getCurrentFailedPasswordAttempts() {
   1433         synchronized (this) {
   1434             // This API can only be called by an active device admin,
   1435             // so try to retrieve it to check that the caller is one.
   1436             getActiveAdminForCallerLocked(null,
   1437                     DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
   1438             return mFailedPasswordAttempts;
   1439         }
   1440     }
   1441 
   1442     public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) {
   1443         synchronized (this) {
   1444             // This API can only be called by an active device admin,
   1445             // so try to retrieve it to check that the caller is one.
   1446             getActiveAdminForCallerLocked(who,
   1447                     DeviceAdminInfo.USES_POLICY_WIPE_DATA);
   1448             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
   1449                     DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
   1450             if (ap.maximumFailedPasswordsForWipe != num) {
   1451                 ap.maximumFailedPasswordsForWipe = num;
   1452                 saveSettingsLocked();
   1453             }
   1454         }
   1455     }
   1456 
   1457     public int getMaximumFailedPasswordsForWipe(ComponentName who) {
   1458         synchronized (this) {
   1459             int count = 0;
   1460 
   1461             if (who != null) {
   1462                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
   1463                 return admin != null ? admin.maximumFailedPasswordsForWipe : count;
   1464             }
   1465 
   1466             final int N = mAdminList.size();
   1467             for  (int i=0; i<N; i++) {
   1468                 ActiveAdmin admin = mAdminList.get(i);
   1469                 if (count == 0) {
   1470                     count = admin.maximumFailedPasswordsForWipe;
   1471                 } else if (admin.maximumFailedPasswordsForWipe != 0
   1472                         && count > admin.maximumFailedPasswordsForWipe) {
   1473                     count = admin.maximumFailedPasswordsForWipe;
   1474                 }
   1475             }
   1476             return count;
   1477         }
   1478     }
   1479 
   1480     public boolean resetPassword(String password, int flags) {
   1481         int quality;
   1482         synchronized (this) {
   1483             // This API can only be called by an active device admin,
   1484             // so try to retrieve it to check that the caller is one.
   1485             getActiveAdminForCallerLocked(null,
   1486                     DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
   1487             quality = getPasswordQuality(null);
   1488             if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
   1489                 int realQuality = LockPatternUtils.computePasswordQuality(password);
   1490                 if (realQuality < quality
   1491                         && quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
   1492                     Slog.w(TAG, "resetPassword: password quality 0x"
   1493                             + Integer.toHexString(quality)
   1494                             + " does not meet required quality 0x"
   1495                             + Integer.toHexString(quality));
   1496                     return false;
   1497                 }
   1498                 quality = Math.max(realQuality, quality);
   1499             }
   1500             int length = getPasswordMinimumLength(null);
   1501             if (password.length() < length) {
   1502                 Slog.w(TAG, "resetPassword: password length " + password.length()
   1503                         + " does not meet required length " + length);
   1504                 return false;
   1505             }
   1506             if (quality == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
   1507                 int letters = 0;
   1508                 int uppercase = 0;
   1509                 int lowercase = 0;
   1510                 int numbers = 0;
   1511                 int symbols = 0;
   1512                 int nonletter = 0;
   1513                 for (int i = 0; i < password.length(); i++) {
   1514                     char c = password.charAt(i);
   1515                     if (c >= 'A' && c <= 'Z') {
   1516                         letters++;
   1517                         uppercase++;
   1518                     } else if (c >= 'a' && c <= 'z') {
   1519                         letters++;
   1520                         lowercase++;
   1521                     } else if (c >= '0' && c <= '9') {
   1522                         numbers++;
   1523                         nonletter++;
   1524                     } else {
   1525                         symbols++;
   1526                         nonletter++;
   1527                     }
   1528                 }
   1529                 int neededLetters = getPasswordMinimumLetters(null);
   1530                 if(letters < neededLetters) {
   1531                     Slog.w(TAG, "resetPassword: number of letters " + letters
   1532                             + " does not meet required number of letters " + neededLetters);
   1533                     return false;
   1534                 }
   1535                 int neededNumbers = getPasswordMinimumNumeric(null);
   1536                 if (numbers < neededNumbers) {
   1537                     Slog
   1538                             .w(TAG, "resetPassword: number of numerical digits " + numbers
   1539                                     + " does not meet required number of numerical digits "
   1540                                     + neededNumbers);
   1541                     return false;
   1542                 }
   1543                 int neededLowerCase = getPasswordMinimumLowerCase(null);
   1544                 if (lowercase < neededLowerCase) {
   1545                     Slog.w(TAG, "resetPassword: number of lowercase letters " + lowercase
   1546                             + " does not meet required number of lowercase letters "
   1547                             + neededLowerCase);
   1548                     return false;
   1549                 }
   1550                 int neededUpperCase = getPasswordMinimumUpperCase(null);
   1551                 if (uppercase < neededUpperCase) {
   1552                     Slog.w(TAG, "resetPassword: number of uppercase letters " + uppercase
   1553                             + " does not meet required number of uppercase letters "
   1554                             + neededUpperCase);
   1555                     return false;
   1556                 }
   1557                 int neededSymbols = getPasswordMinimumSymbols(null);
   1558                 if (symbols < neededSymbols) {
   1559                     Slog.w(TAG, "resetPassword: number of special symbols " + symbols
   1560                             + " does not meet required number of special symbols " + neededSymbols);
   1561                     return false;
   1562                 }
   1563                 int neededNonLetter = getPasswordMinimumNonLetter(null);
   1564                 if (nonletter < neededNonLetter) {
   1565                     Slog.w(TAG, "resetPassword: number of non-letter characters " + nonletter
   1566                             + " does not meet required number of non-letter characters "
   1567                             + neededNonLetter);
   1568                     return false;
   1569                 }
   1570             }
   1571         }
   1572 
   1573         int callingUid = Binder.getCallingUid();
   1574         if (mPasswordOwner >= 0 && mPasswordOwner != callingUid) {
   1575             Slog.w(TAG, "resetPassword: already set by another uid and not entered by user");
   1576             return false;
   1577         }
   1578 
   1579         // Don't do this with the lock held, because it is going to call
   1580         // back in to the service.
   1581         long ident = Binder.clearCallingIdentity();
   1582         try {
   1583             LockPatternUtils utils = new LockPatternUtils(mContext);
   1584             utils.saveLockPassword(password, quality);
   1585             synchronized (this) {
   1586                 int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY)
   1587                         != 0 ? callingUid : -1;
   1588                 if (mPasswordOwner != newOwner) {
   1589                     mPasswordOwner = newOwner;
   1590                     saveSettingsLocked();
   1591                 }
   1592             }
   1593         } finally {
   1594             Binder.restoreCallingIdentity(ident);
   1595         }
   1596 
   1597         return true;
   1598     }
   1599 
   1600     public void setMaximumTimeToLock(ComponentName who, long timeMs) {
   1601         synchronized (this) {
   1602             if (who == null) {
   1603                 throw new NullPointerException("ComponentName is null");
   1604             }
   1605             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
   1606                     DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
   1607             if (ap.maximumTimeToUnlock != timeMs) {
   1608                 ap.maximumTimeToUnlock = timeMs;
   1609 
   1610                 long ident = Binder.clearCallingIdentity();
   1611                 try {
   1612                     saveSettingsLocked();
   1613 
   1614                     timeMs = getMaximumTimeToLock(null);
   1615                     if (timeMs <= 0) {
   1616                         timeMs = Integer.MAX_VALUE;
   1617                     }
   1618 
   1619                     try {
   1620                         getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
   1621                     } catch (RemoteException e) {
   1622                         Slog.w(TAG, "Failure talking with power manager", e);
   1623                     }
   1624                 } finally {
   1625                     Binder.restoreCallingIdentity(ident);
   1626                 }
   1627             }
   1628         }
   1629     }
   1630 
   1631     public long getMaximumTimeToLock(ComponentName who) {
   1632         synchronized (this) {
   1633             long time = 0;
   1634 
   1635             if (who != null) {
   1636                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
   1637                 return admin != null ? admin.maximumTimeToUnlock : time;
   1638             }
   1639 
   1640             final int N = mAdminList.size();
   1641             for  (int i=0; i<N; i++) {
   1642                 ActiveAdmin admin = mAdminList.get(i);
   1643                 if (time == 0) {
   1644                     time = admin.maximumTimeToUnlock;
   1645                 } else if (admin.maximumTimeToUnlock != 0
   1646                         && time > admin.maximumTimeToUnlock) {
   1647                     time = admin.maximumTimeToUnlock;
   1648                 }
   1649             }
   1650             return time;
   1651         }
   1652     }
   1653 
   1654     public void lockNow() {
   1655         synchronized (this) {
   1656             // This API can only be called by an active device admin,
   1657             // so try to retrieve it to check that the caller is one.
   1658             getActiveAdminForCallerLocked(null,
   1659                     DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
   1660             long ident = Binder.clearCallingIdentity();
   1661             try {
   1662                 // Power off the display
   1663                 mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(),
   1664                         WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN);
   1665                 // Ensure the device is locked
   1666                 getWindowManager().lockNow();
   1667             } catch (RemoteException e) {
   1668             } finally {
   1669                 Binder.restoreCallingIdentity(ident);
   1670             }
   1671         }
   1672     }
   1673 
   1674     private boolean isExtStorageEncrypted() {
   1675         String state = SystemProperties.get("vold.decrypt");
   1676         return !"".equals(state);
   1677     }
   1678 
   1679     void wipeDataLocked(int flags) {
   1680         // If the SD card is encrypted and non-removable, we have to force a wipe.
   1681         boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted();
   1682         boolean wipeExtRequested = (flags&DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0;
   1683 
   1684         // Note: we can only do the wipe via ExternalStorageFormatter if the volume is not emulated.
   1685         if ((forceExtWipe || wipeExtRequested) && !Environment.isExternalStorageEmulated()) {
   1686             Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
   1687             intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
   1688             mWakeLock.acquire(10000);
   1689             mContext.startService(intent);
   1690         } else {
   1691             try {
   1692                 RecoverySystem.rebootWipeUserData(mContext);
   1693             } catch (IOException e) {
   1694                 Slog.w(TAG, "Failed requesting data wipe", e);
   1695             }
   1696         }
   1697     }
   1698 
   1699     public void wipeData(int flags) {
   1700         synchronized (this) {
   1701             // This API can only be called by an active device admin,
   1702             // so try to retrieve it to check that the caller is one.
   1703             getActiveAdminForCallerLocked(null,
   1704                     DeviceAdminInfo.USES_POLICY_WIPE_DATA);
   1705             long ident = Binder.clearCallingIdentity();
   1706             try {
   1707                 wipeDataLocked(flags);
   1708             } finally {
   1709                 Binder.restoreCallingIdentity(ident);
   1710             }
   1711         }
   1712     }
   1713 
   1714     public void getRemoveWarning(ComponentName comp, final RemoteCallback result) {
   1715         mContext.enforceCallingOrSelfPermission(
   1716                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
   1717 
   1718         synchronized (this) {
   1719             ActiveAdmin admin = getActiveAdminUncheckedLocked(comp);
   1720             if (admin == null) {
   1721                 try {
   1722                     result.sendResult(null);
   1723                 } catch (RemoteException e) {
   1724                 }
   1725                 return;
   1726             }
   1727             Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
   1728             intent.setComponent(admin.info.getComponent());
   1729             mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
   1730                 @Override
   1731                 public void onReceive(Context context, Intent intent) {
   1732                     try {
   1733                         result.sendResult(getResultExtras(false));
   1734                     } catch (RemoteException e) {
   1735                     }
   1736                 }
   1737             }, null, Activity.RESULT_OK, null, null);
   1738         }
   1739     }
   1740 
   1741     public void setActivePasswordState(int quality, int length, int letters, int uppercase,
   1742             int lowercase, int numbers, int symbols, int nonletter) {
   1743         mContext.enforceCallingOrSelfPermission(
   1744                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
   1745 
   1746         validateQualityConstant(quality);
   1747 
   1748         synchronized (this) {
   1749             if (mActivePasswordQuality != quality || mActivePasswordLength != length
   1750                     || mFailedPasswordAttempts != 0 || mActivePasswordLetters != letters
   1751                     || mActivePasswordUpperCase != uppercase
   1752                     || mActivePasswordLowerCase != lowercase || mActivePasswordNumeric != numbers
   1753                     || mActivePasswordSymbols != symbols || mActivePasswordNonLetter != nonletter) {
   1754                 long ident = Binder.clearCallingIdentity();
   1755                 try {
   1756                     mActivePasswordQuality = quality;
   1757                     mActivePasswordLength = length;
   1758                     mActivePasswordLetters = letters;
   1759                     mActivePasswordLowerCase = lowercase;
   1760                     mActivePasswordUpperCase = uppercase;
   1761                     mActivePasswordNumeric = numbers;
   1762                     mActivePasswordSymbols = symbols;
   1763                     mActivePasswordNonLetter = nonletter;
   1764                     mFailedPasswordAttempts = 0;
   1765                     saveSettingsLocked();
   1766                     updatePasswordExpirationsLocked();
   1767                     setExpirationAlarmCheckLocked(mContext);
   1768                     sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
   1769                             DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
   1770                 } finally {
   1771                     Binder.restoreCallingIdentity(ident);
   1772                 }
   1773             }
   1774         }
   1775     }
   1776 
   1777     /**
   1778      * Called any time the device password is updated.  Resets all password expiration clocks.
   1779      */
   1780     private void updatePasswordExpirationsLocked() {
   1781         final int N = mAdminList.size();
   1782         if (N > 0) {
   1783             for (int i=0; i<N; i++) {
   1784                 ActiveAdmin admin = mAdminList.get(i);
   1785                 if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) {
   1786                     long timeout = admin.passwordExpirationTimeout;
   1787                     long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L;
   1788                     admin.passwordExpirationDate = expiration;
   1789                 }
   1790             }
   1791             saveSettingsLocked();
   1792         }
   1793     }
   1794 
   1795     public void reportFailedPasswordAttempt() {
   1796         mContext.enforceCallingOrSelfPermission(
   1797                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
   1798 
   1799         synchronized (this) {
   1800             long ident = Binder.clearCallingIdentity();
   1801             try {
   1802                 mFailedPasswordAttempts++;
   1803                 saveSettingsLocked();
   1804                 int max = getMaximumFailedPasswordsForWipe(null);
   1805                 if (max > 0 && mFailedPasswordAttempts >= max) {
   1806                     wipeDataLocked(0);
   1807                 }
   1808                 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
   1809                         DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
   1810             } finally {
   1811                 Binder.restoreCallingIdentity(ident);
   1812             }
   1813         }
   1814     }
   1815 
   1816     public void reportSuccessfulPasswordAttempt() {
   1817         mContext.enforceCallingOrSelfPermission(
   1818                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
   1819 
   1820         synchronized (this) {
   1821             if (mFailedPasswordAttempts != 0 || mPasswordOwner >= 0) {
   1822                 long ident = Binder.clearCallingIdentity();
   1823                 try {
   1824                     mFailedPasswordAttempts = 0;
   1825                     mPasswordOwner = -1;
   1826                     saveSettingsLocked();
   1827                     sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
   1828                             DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
   1829                 } finally {
   1830                     Binder.restoreCallingIdentity(ident);
   1831                 }
   1832             }
   1833         }
   1834     }
   1835 
   1836     public ComponentName setGlobalProxy(ComponentName who, String proxySpec,
   1837             String exclusionList) {
   1838         synchronized(this) {
   1839             if (who == null) {
   1840                 throw new NullPointerException("ComponentName is null");
   1841             }
   1842 
   1843             ActiveAdmin admin = getActiveAdminForCallerLocked(who,
   1844                     DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
   1845 
   1846             // Scan through active admins and find if anyone has already
   1847             // set the global proxy.
   1848             Set<ComponentName> compSet = mAdminMap.keySet();
   1849             for  (ComponentName component : compSet) {
   1850                 ActiveAdmin ap = mAdminMap.get(component);
   1851                 if ((ap.specifiesGlobalProxy) && (!component.equals(who))) {
   1852                     // Another admin already sets the global proxy
   1853                     // Return it to the caller.
   1854                     return component;
   1855                 }
   1856             }
   1857             if (proxySpec == null) {
   1858                 admin.specifiesGlobalProxy = false;
   1859                 admin.globalProxySpec = null;
   1860                 admin.globalProxyExclusionList = null;
   1861             } else {
   1862 
   1863                 admin.specifiesGlobalProxy = true;
   1864                 admin.globalProxySpec = proxySpec;
   1865                 admin.globalProxyExclusionList = exclusionList;
   1866             }
   1867 
   1868             // Reset the global proxy accordingly
   1869             // Do this using system permissions, as apps cannot write to secure settings
   1870             long origId = Binder.clearCallingIdentity();
   1871             resetGlobalProxy();
   1872             Binder.restoreCallingIdentity(origId);
   1873             return null;
   1874         }
   1875     }
   1876 
   1877     public ComponentName getGlobalProxyAdmin() {
   1878         synchronized(this) {
   1879             // Scan through active admins and find if anyone has already
   1880             // set the global proxy.
   1881             final int N = mAdminList.size();
   1882             for (int i = 0; i < N; i++) {
   1883                 ActiveAdmin ap = mAdminList.get(i);
   1884                 if (ap.specifiesGlobalProxy) {
   1885                     // Device admin sets the global proxy
   1886                     // Return it to the caller.
   1887                     return ap.info.getComponent();
   1888                 }
   1889             }
   1890         }
   1891         // No device admin sets the global proxy.
   1892         return null;
   1893     }
   1894 
   1895     private void resetGlobalProxy() {
   1896         final int N = mAdminList.size();
   1897         for (int i = 0; i < N; i++) {
   1898             ActiveAdmin ap = mAdminList.get(i);
   1899             if (ap.specifiesGlobalProxy) {
   1900                 saveGlobalProxy(ap.globalProxySpec, ap.globalProxyExclusionList);
   1901                 return;
   1902             }
   1903         }
   1904         // No device admins defining global proxies - reset global proxy settings to none
   1905         saveGlobalProxy(null, null);
   1906     }
   1907 
   1908     private void saveGlobalProxy(String proxySpec, String exclusionList) {
   1909         if (exclusionList == null) {
   1910             exclusionList = "";
   1911         }
   1912         if (proxySpec == null) {
   1913             proxySpec = "";
   1914         }
   1915         // Remove white spaces
   1916         proxySpec = proxySpec.trim();
   1917         String data[] = proxySpec.split(":");
   1918         int proxyPort = 8080;
   1919         if (data.length > 1) {
   1920             try {
   1921                 proxyPort = Integer.parseInt(data[1]);
   1922             } catch (NumberFormatException e) {}
   1923         }
   1924         exclusionList = exclusionList.trim();
   1925         ContentResolver res = mContext.getContentResolver();
   1926         Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_HOST, data[0]);
   1927         Settings.Secure.putInt(res, Settings.Secure.GLOBAL_HTTP_PROXY_PORT, proxyPort);
   1928         Settings.Secure.putString(res, Settings.Secure.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
   1929                 exclusionList);
   1930     }
   1931 
   1932     /**
   1933      * Set the storage encryption request for a single admin.  Returns the new total request
   1934      * status (for all admins).
   1935      */
   1936     public int setStorageEncryption(ComponentName who, boolean encrypt) {
   1937         synchronized (this) {
   1938             // Check for permissions
   1939             if (who == null) {
   1940                 throw new NullPointerException("ComponentName is null");
   1941             }
   1942             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
   1943                     DeviceAdminInfo.USES_ENCRYPTED_STORAGE);
   1944 
   1945             // Quick exit:  If the filesystem does not support encryption, we can exit early.
   1946             if (!isEncryptionSupported()) {
   1947                 return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
   1948             }
   1949 
   1950             // (1) Record the value for the admin so it's sticky
   1951             if (ap.encryptionRequested != encrypt) {
   1952                 ap.encryptionRequested = encrypt;
   1953                 saveSettingsLocked();
   1954             }
   1955 
   1956             // (2) Compute "max" for all admins
   1957             boolean newRequested = false;
   1958             final int N = mAdminList.size();
   1959             for (int i = 0; i < N; i++) {
   1960                 newRequested |= mAdminList.get(i).encryptionRequested;
   1961             }
   1962 
   1963             // Notify OS of new request
   1964             setEncryptionRequested(newRequested);
   1965 
   1966             // Return the new global request status
   1967             return newRequested
   1968                     ? DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE
   1969                     : DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
   1970         }
   1971     }
   1972 
   1973     /**
   1974      * Get the current storage encryption request status for a given admin, or aggregate of all
   1975      * active admins.
   1976      */
   1977     public boolean getStorageEncryption(ComponentName who) {
   1978         synchronized (this) {
   1979             // Check for permissions if a particular caller is specified
   1980             if (who != null) {
   1981                 // When checking for a single caller, status is based on caller's request
   1982                 ActiveAdmin ap = getActiveAdminUncheckedLocked(who);
   1983                 return ap != null ? ap.encryptionRequested : false;
   1984             }
   1985 
   1986             // If no particular caller is specified, return the aggregate set of requests.
   1987             // This is short circuited by returning true on the first hit.
   1988             final int N = mAdminList.size();
   1989             for (int i = 0; i < N; i++) {
   1990                 if (mAdminList.get(i).encryptionRequested) {
   1991                     return true;
   1992                 }
   1993             }
   1994             return false;
   1995         }
   1996     }
   1997 
   1998     /**
   1999      * Get the current encryption status of the device.
   2000      */
   2001     public int getStorageEncryptionStatus() {
   2002         return getEncryptionStatus();
   2003     }
   2004 
   2005     /**
   2006      * Hook to low-levels:  This should report if the filesystem supports encrypted storage.
   2007      */
   2008     private boolean isEncryptionSupported() {
   2009         // Note, this can be implemented as
   2010         //   return getEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
   2011         // But is provided as a separate internal method if there's a faster way to do a
   2012         // simple check for supported-or-not.
   2013         return getEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
   2014     }
   2015 
   2016     /**
   2017      * Hook to low-levels:  Reporting the current status of encryption.
   2018      * @return A value such as {@link DevicePolicyManager#ENCRYPTION_STATUS_UNSUPPORTED} or
   2019      * {@link DevicePolicyManager#ENCRYPTION_STATUS_INACTIVE} or
   2020      * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE}.
   2021      */
   2022     private int getEncryptionStatus() {
   2023         String status = SystemProperties.get("ro.crypto.state", "unsupported");
   2024         if ("encrypted".equalsIgnoreCase(status)) {
   2025             return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE;
   2026         } else if ("unencrypted".equalsIgnoreCase(status)) {
   2027             return DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
   2028         } else {
   2029             return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
   2030         }
   2031     }
   2032 
   2033     /**
   2034      * Hook to low-levels:  If needed, record the new admin setting for encryption.
   2035      */
   2036     private void setEncryptionRequested(boolean encrypt) {
   2037     }
   2038 
   2039     /**
   2040      * The system property used to share the state of the camera. The native camera service
   2041      * is expected to read this property and act accordingly.
   2042      */
   2043     public static final String SYSTEM_PROP_DISABLE_CAMERA = "sys.secpolicy.camera.disabled";
   2044 
   2045     /**
   2046      * Disables all device cameras according to the specified admin.
   2047      */
   2048     public void setCameraDisabled(ComponentName who, boolean disabled) {
   2049         synchronized (this) {
   2050             if (who == null) {
   2051                 throw new NullPointerException("ComponentName is null");
   2052             }
   2053             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
   2054                     DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA);
   2055             if (ap.disableCamera != disabled) {
   2056                 ap.disableCamera = disabled;
   2057                 saveSettingsLocked();
   2058             }
   2059             syncDeviceCapabilitiesLocked();
   2060         }
   2061     }
   2062 
   2063     /**
   2064      * Gets whether or not all device cameras are disabled for a given admin, or disabled for any
   2065      * active admins.
   2066      */
   2067     public boolean getCameraDisabled(ComponentName who) {
   2068         synchronized (this) {
   2069             if (who != null) {
   2070                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
   2071                 return (admin != null) ? admin.disableCamera : false;
   2072             }
   2073 
   2074             // Determine whether or not the device camera is disabled for any active admins.
   2075             final int N = mAdminList.size();
   2076             for (int i = 0; i < N; i++) {
   2077                 ActiveAdmin admin = mAdminList.get(i);
   2078                 if (admin.disableCamera) {
   2079                     return true;
   2080                 }
   2081             }
   2082             return false;
   2083         }
   2084     }
   2085 
   2086     @Override
   2087     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   2088         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
   2089                 != PackageManager.PERMISSION_GRANTED) {
   2090 
   2091             pw.println("Permission Denial: can't dump DevicePolicyManagerService from from pid="
   2092                     + Binder.getCallingPid()
   2093                     + ", uid=" + Binder.getCallingUid());
   2094             return;
   2095         }
   2096 
   2097         final Printer p = new PrintWriterPrinter(pw);
   2098 
   2099         synchronized (this) {
   2100             p.println("Current Device Policy Manager state:");
   2101 
   2102             p.println("  Enabled Device Admins:");
   2103             final int N = mAdminList.size();
   2104             for (int i=0; i<N; i++) {
   2105                 ActiveAdmin ap = mAdminList.get(i);
   2106                 if (ap != null) {
   2107                     pw.print("  "); pw.print(ap.info.getComponent().flattenToShortString());
   2108                             pw.println(":");
   2109                     ap.dump("    ", pw);
   2110                 }
   2111             }
   2112 
   2113             pw.println(" ");
   2114             pw.print("  mActivePasswordQuality=0x");
   2115                     pw.println(Integer.toHexString(mActivePasswordQuality));
   2116             pw.print("  mActivePasswordLength="); pw.println(mActivePasswordLength);
   2117             pw.print("  mActivePasswordUpperCase="); pw.println(mActivePasswordUpperCase);
   2118             pw.print("  mActivePasswordLowerCase="); pw.println(mActivePasswordLowerCase);
   2119             pw.print("  mActivePasswordLetters="); pw.println(mActivePasswordLetters);
   2120             pw.print("  mActivePasswordNumeric="); pw.println(mActivePasswordNumeric);
   2121             pw.print("  mActivePasswordSymbols="); pw.println(mActivePasswordSymbols);
   2122             pw.print("  mActivePasswordNonLetter="); pw.println(mActivePasswordNonLetter);
   2123             pw.print("  mFailedPasswordAttempts="); pw.println(mFailedPasswordAttempts);
   2124             pw.print("  mPasswordOwner="); pw.println(mPasswordOwner);
   2125         }
   2126     }
   2127 }
   2128