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