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