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.admin.DeviceAdminInfo;
     32 import android.app.admin.DeviceAdminReceiver;
     33 import android.app.admin.DevicePolicyManager;
     34 import android.app.admin.IDevicePolicyManager;
     35 import android.content.BroadcastReceiver;
     36 import android.content.ComponentName;
     37 import android.content.Context;
     38 import android.content.Intent;
     39 import android.content.pm.PackageManager;
     40 import android.content.pm.ResolveInfo;
     41 import android.content.pm.PackageManager.NameNotFoundException;
     42 import android.os.Binder;
     43 import android.os.IBinder;
     44 import android.os.IPowerManager;
     45 import android.os.PowerManager;
     46 import android.os.RecoverySystem;
     47 import android.os.RemoteCallback;
     48 import android.os.RemoteException;
     49 import android.os.ServiceManager;
     50 import android.os.SystemClock;
     51 import android.util.Slog;
     52 import android.util.PrintWriterPrinter;
     53 import android.util.Printer;
     54 import android.util.Xml;
     55 import android.view.WindowManagerPolicy;
     56 
     57 import java.io.File;
     58 import java.io.FileDescriptor;
     59 import java.io.FileInputStream;
     60 import java.io.FileNotFoundException;
     61 import java.io.FileOutputStream;
     62 import java.io.IOException;
     63 import java.io.PrintWriter;
     64 import java.util.ArrayList;
     65 import java.util.HashMap;
     66 import java.util.List;
     67 
     68 /**
     69  * Implementation of the device policy APIs.
     70  */
     71 public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
     72     static final String TAG = "DevicePolicyManagerService";
     73 
     74     final Context mContext;
     75     final MyPackageMonitor mMonitor;
     76     final PowerManager.WakeLock mWakeLock;
     77 
     78     IPowerManager mIPowerManager;
     79 
     80     int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
     81     int mActivePasswordLength = 0;
     82     int mFailedPasswordAttempts = 0;
     83 
     84     int mPasswordOwner = -1;
     85 
     86     final HashMap<ComponentName, ActiveAdmin> mAdminMap
     87             = new HashMap<ComponentName, ActiveAdmin>();
     88     final ArrayList<ActiveAdmin> mAdminList
     89             = new ArrayList<ActiveAdmin>();
     90 
     91     static class ActiveAdmin {
     92         final DeviceAdminInfo info;
     93 
     94         int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
     95         int minimumPasswordLength = 0;
     96         long maximumTimeToUnlock = 0;
     97         int maximumFailedPasswordsForWipe = 0;
     98 
     99         ActiveAdmin(DeviceAdminInfo _info) {
    100             info = _info;
    101         }
    102 
    103         int getUid() { return info.getActivityInfo().applicationInfo.uid; }
    104 
    105         void writeToXml(XmlSerializer out)
    106                 throws IllegalArgumentException, IllegalStateException, IOException {
    107             out.startTag(null, "policies");
    108             info.writePoliciesToXml(out);
    109             out.endTag(null, "policies");
    110             if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
    111                 out.startTag(null, "password-quality");
    112                 out.attribute(null, "value", Integer.toString(passwordQuality));
    113                 out.endTag(null, "password-quality");
    114                 if (minimumPasswordLength > 0) {
    115                     out.startTag(null, "min-password-length");
    116                     out.attribute(null, "value", Integer.toString(minimumPasswordLength));
    117                     out.endTag(null, "mn-password-length");
    118                 }
    119             }
    120             if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
    121                 out.startTag(null, "max-time-to-unlock");
    122                 out.attribute(null, "value", Long.toString(maximumTimeToUnlock));
    123                 out.endTag(null, "max-time-to-unlock");
    124             }
    125             if (maximumFailedPasswordsForWipe != 0) {
    126                 out.startTag(null, "max-failed-password-wipe");
    127                 out.attribute(null, "value", Integer.toString(maximumFailedPasswordsForWipe));
    128                 out.endTag(null, "max-failed-password-wipe");
    129             }
    130         }
    131 
    132         void readFromXml(XmlPullParser parser)
    133                 throws XmlPullParserException, IOException {
    134             int outerDepth = parser.getDepth();
    135             int type;
    136             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
    137                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
    138                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
    139                     continue;
    140                 }
    141                 String tag = parser.getName();
    142                 if ("policies".equals(tag)) {
    143                     info.readPoliciesFromXml(parser);
    144                 } else if ("password-quality".equals(tag)) {
    145                     passwordQuality = Integer.parseInt(
    146                             parser.getAttributeValue(null, "value"));
    147                 } else if ("min-password-length".equals(tag)) {
    148                     minimumPasswordLength = Integer.parseInt(
    149                             parser.getAttributeValue(null, "value"));
    150                 } else if ("max-time-to-unlock".equals(tag)) {
    151                     maximumTimeToUnlock = Long.parseLong(
    152                             parser.getAttributeValue(null, "value"));
    153                 } else if ("max-failed-password-wipe".equals(tag)) {
    154                     maximumFailedPasswordsForWipe = Integer.parseInt(
    155                             parser.getAttributeValue(null, "value"));
    156                 } else {
    157                     Slog.w(TAG, "Unknown admin tag: " + tag);
    158                 }
    159                 XmlUtils.skipCurrentTag(parser);
    160             }
    161         }
    162 
    163         void dump(String prefix, PrintWriter pw) {
    164             pw.print(prefix); pw.print("uid="); pw.println(getUid());
    165             pw.print(prefix); pw.println("policies:");
    166             ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies();
    167             if (pols != null) {
    168                 for (int i=0; i<pols.size(); i++) {
    169                     pw.print(prefix); pw.print("  "); pw.println(pols.get(i).tag);
    170                 }
    171             }
    172             pw.print(prefix); pw.print("passwordQuality=0x");
    173                     pw.print(Integer.toHexString(passwordQuality));
    174                     pw.print(" minimumPasswordLength=");
    175                     pw.println(minimumPasswordLength);
    176             pw.print(prefix); pw.print("maximumTimeToUnlock=");
    177                     pw.println(maximumTimeToUnlock);
    178             pw.print(prefix); pw.print("maximumFailedPasswordsForWipe=");
    179                     pw.println(maximumFailedPasswordsForWipe);
    180         }
    181     }
    182 
    183     class MyPackageMonitor extends PackageMonitor {
    184         public void onSomePackagesChanged() {
    185             synchronized (DevicePolicyManagerService.this) {
    186                 boolean removed = false;
    187                 for (int i=mAdminList.size()-1; i>=0; i--) {
    188                     ActiveAdmin aa = mAdminList.get(i);
    189                     int change = isPackageDisappearing(aa.info.getPackageName());
    190                     if (change == PACKAGE_PERMANENT_CHANGE
    191                             || change == PACKAGE_TEMPORARY_CHANGE) {
    192                         Slog.w(TAG, "Admin unexpectedly uninstalled: "
    193                                 + aa.info.getComponent());
    194                         removed = true;
    195                         mAdminList.remove(i);
    196                     } else if (isPackageModified(aa.info.getPackageName())) {
    197                         try {
    198                             mContext.getPackageManager().getReceiverInfo(
    199                                     aa.info.getComponent(), 0);
    200                         } catch (NameNotFoundException e) {
    201                             Slog.w(TAG, "Admin package change removed component: "
    202                                     + aa.info.getComponent());
    203                             removed = true;
    204                             mAdminList.remove(i);
    205                         }
    206                     }
    207                 }
    208                 if (removed) {
    209                     validatePasswordOwnerLocked();
    210                 }
    211             }
    212         }
    213     }
    214 
    215     /**
    216      * Instantiates the service.
    217      */
    218     public DevicePolicyManagerService(Context context) {
    219         mContext = context;
    220         mMonitor = new MyPackageMonitor();
    221         mMonitor.register(context, true);
    222         mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE))
    223                 .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM");
    224     }
    225 
    226     private IPowerManager getIPowerManager() {
    227         if (mIPowerManager == null) {
    228             IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
    229             mIPowerManager = IPowerManager.Stub.asInterface(b);
    230         }
    231         return mIPowerManager;
    232     }
    233 
    234     ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) {
    235         ActiveAdmin admin = mAdminMap.get(who);
    236         if (admin != null
    237                 && who.getPackageName().equals(admin.info.getActivityInfo().packageName)
    238                 && who.getClassName().equals(admin.info.getActivityInfo().name)) {
    239             return admin;
    240         }
    241         return null;
    242     }
    243 
    244     ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
    245             throws SecurityException {
    246         final int callingUid = Binder.getCallingUid();
    247         if (who != null) {
    248             ActiveAdmin admin = mAdminMap.get(who);
    249             if (admin == null) {
    250                 throw new SecurityException("No active admin " + who);
    251             }
    252             if (admin.getUid() != callingUid) {
    253                 throw new SecurityException("Admin " + who + " is not owned by uid "
    254                         + Binder.getCallingUid());
    255             }
    256             if (!admin.info.usesPolicy(reqPolicy)) {
    257                 throw new SecurityException("Admin " + admin.info.getComponent()
    258                         + " did not specify uses-policy for: "
    259                         + admin.info.getTagForPolicy(reqPolicy));
    260             }
    261             return admin;
    262         } else {
    263             final int N = mAdminList.size();
    264             for (int i=0; i<N; i++) {
    265                 ActiveAdmin admin = mAdminList.get(i);
    266                 if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) {
    267                     return admin;
    268                 }
    269             }
    270             throw new SecurityException("No active admin owned by uid "
    271                     + Binder.getCallingUid() + " for policy #" + reqPolicy);
    272         }
    273     }
    274 
    275     void sendAdminCommandLocked(ActiveAdmin admin, String action) {
    276         Intent intent = new Intent(action);
    277         intent.setComponent(admin.info.getComponent());
    278         mContext.sendBroadcast(intent);
    279     }
    280 
    281     void sendAdminCommandLocked(String action, int reqPolicy) {
    282         final int N = mAdminList.size();
    283         if (N > 0) {
    284             for (int i=0; i<N; i++) {
    285                 ActiveAdmin admin = mAdminList.get(i);
    286                 if (admin.info.usesPolicy(reqPolicy)) {
    287                     sendAdminCommandLocked(admin, action);
    288                 }
    289             }
    290         }
    291     }
    292 
    293     void removeActiveAdminLocked(ComponentName adminReceiver) {
    294         ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
    295         if (admin != null) {
    296             sendAdminCommandLocked(admin,
    297                     DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED);
    298             // XXX need to wait for it to complete.
    299             mAdminList.remove(admin);
    300             mAdminMap.remove(adminReceiver);
    301             validatePasswordOwnerLocked();
    302         }
    303     }
    304 
    305     public DeviceAdminInfo findAdmin(ComponentName adminName) {
    306         Intent resolveIntent = new Intent();
    307         resolveIntent.setComponent(adminName);
    308         List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceivers(
    309                 resolveIntent, PackageManager.GET_META_DATA);
    310         if (infos == null || infos.size() <= 0) {
    311             throw new IllegalArgumentException("Unknown admin: " + adminName);
    312         }
    313 
    314         try {
    315             return new DeviceAdminInfo(mContext, infos.get(0));
    316         } catch (XmlPullParserException e) {
    317             Slog.w(TAG, "Bad device admin requested: " + adminName, e);
    318             return null;
    319         } catch (IOException e) {
    320             Slog.w(TAG, "Bad device admin requested: " + adminName, e);
    321             return null;
    322         }
    323     }
    324 
    325     private static JournaledFile makeJournaledFile() {
    326         final String base = "/data/system/device_policies.xml";
    327         return new JournaledFile(new File(base), new File(base + ".tmp"));
    328     }
    329 
    330     private void saveSettingsLocked() {
    331         JournaledFile journal = makeJournaledFile();
    332         FileOutputStream stream = null;
    333         try {
    334             stream = new FileOutputStream(journal.chooseForWrite(), false);
    335             XmlSerializer out = new FastXmlSerializer();
    336             out.setOutput(stream, "utf-8");
    337             out.startDocument(null, true);
    338 
    339             out.startTag(null, "policies");
    340 
    341             final int N = mAdminList.size();
    342             for (int i=0; i<N; i++) {
    343                 ActiveAdmin ap = mAdminList.get(i);
    344                 if (ap != null) {
    345                     out.startTag(null, "admin");
    346                     out.attribute(null, "name", ap.info.getComponent().flattenToString());
    347                     ap.writeToXml(out);
    348                     out.endTag(null, "admin");
    349                 }
    350             }
    351 
    352             if (mPasswordOwner >= 0) {
    353                 out.startTag(null, "password-owner");
    354                 out.attribute(null, "value", Integer.toString(mPasswordOwner));
    355                 out.endTag(null, "password-owner");
    356             }
    357 
    358             if (mFailedPasswordAttempts != 0) {
    359                 out.startTag(null, "failed-password-attempts");
    360                 out.attribute(null, "value", Integer.toString(mFailedPasswordAttempts));
    361                 out.endTag(null, "failed-password-attempts");
    362             }
    363 
    364             if (mActivePasswordQuality != 0 || mActivePasswordLength != 0) {
    365                 out.startTag(null, "active-password");
    366                 out.attribute(null, "quality", Integer.toString(mActivePasswordQuality));
    367                 out.attribute(null, "length", Integer.toString(mActivePasswordLength));
    368                 out.endTag(null, "active-password");
    369             }
    370 
    371             out.endTag(null, "policies");
    372 
    373             out.endDocument();
    374             stream.close();
    375             journal.commit();
    376             sendChangedNotification();
    377         } catch (IOException e) {
    378             try {
    379                 if (stream != null) {
    380                     stream.close();
    381                 }
    382             } catch (IOException ex) {
    383                 // Ignore
    384             }
    385             journal.rollback();
    386         }
    387     }
    388 
    389     private void sendChangedNotification() {
    390         Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
    391         intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
    392         mContext.sendBroadcast(intent);
    393     }
    394 
    395     private void loadSettingsLocked() {
    396         JournaledFile journal = makeJournaledFile();
    397         FileInputStream stream = null;
    398         File file = journal.chooseForRead();
    399         try {
    400             stream = new FileInputStream(file);
    401             XmlPullParser parser = Xml.newPullParser();
    402             parser.setInput(stream, null);
    403 
    404             int type;
    405             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
    406                     && type != XmlPullParser.START_TAG) {
    407             }
    408             String tag = parser.getName();
    409             if (!"policies".equals(tag)) {
    410                 throw new XmlPullParserException(
    411                         "Settings do not start with policies tag: found " + tag);
    412             }
    413             type = parser.next();
    414             int outerDepth = parser.getDepth();
    415             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
    416                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
    417                 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
    418                     continue;
    419                 }
    420                 tag = parser.getName();
    421                 if ("admin".equals(tag)) {
    422                     String name = parser.getAttributeValue(null, "name");
    423                     try {
    424                         DeviceAdminInfo dai = findAdmin(
    425                                 ComponentName.unflattenFromString(name));
    426                         if (dai != null) {
    427                             ActiveAdmin ap = new ActiveAdmin(dai);
    428                             ap.readFromXml(parser);
    429                             mAdminMap.put(ap.info.getComponent(), ap);
    430                             mAdminList.add(ap);
    431                         }
    432                     } catch (RuntimeException e) {
    433                         Slog.w(TAG, "Failed loading admin " + name, e);
    434                     }
    435                 } else if ("failed-password-attempts".equals(tag)) {
    436                     mFailedPasswordAttempts = Integer.parseInt(
    437                             parser.getAttributeValue(null, "value"));
    438                     XmlUtils.skipCurrentTag(parser);
    439                 } else if ("password-owner".equals(tag)) {
    440                     mPasswordOwner = Integer.parseInt(
    441                             parser.getAttributeValue(null, "value"));
    442                     XmlUtils.skipCurrentTag(parser);
    443                 } else if ("active-password".equals(tag)) {
    444                     mActivePasswordQuality = Integer.parseInt(
    445                             parser.getAttributeValue(null, "quality"));
    446                     mActivePasswordLength = Integer.parseInt(
    447                             parser.getAttributeValue(null, "length"));
    448                     XmlUtils.skipCurrentTag(parser);
    449                 } else {
    450                     Slog.w(TAG, "Unknown tag: " + tag);
    451                     XmlUtils.skipCurrentTag(parser);
    452                 }
    453             }
    454         } catch (NullPointerException e) {
    455             Slog.w(TAG, "failed parsing " + file + " " + e);
    456         } catch (NumberFormatException e) {
    457             Slog.w(TAG, "failed parsing " + file + " " + e);
    458         } catch (XmlPullParserException e) {
    459             Slog.w(TAG, "failed parsing " + file + " " + e);
    460         } catch (FileNotFoundException e) {
    461             // Don't be noisy, this is normal if we haven't defined any policies.
    462         } catch (IOException e) {
    463             Slog.w(TAG, "failed parsing " + file + " " + e);
    464         } catch (IndexOutOfBoundsException e) {
    465             Slog.w(TAG, "failed parsing " + file + " " + e);
    466         }
    467         try {
    468             if (stream != null) {
    469                 stream.close();
    470             }
    471         } catch (IOException e) {
    472             // Ignore
    473         }
    474 
    475         // Validate that what we stored for the password quality matches
    476         // sufficiently what is currently set.  Note that this is only
    477         // a sanity check in case the two get out of sync; this should
    478         // never normally happen.
    479         LockPatternUtils utils = new LockPatternUtils(mContext);
    480         if (utils.getActivePasswordQuality() < mActivePasswordQuality) {
    481             Slog.w(TAG, "Active password quality 0x"
    482                     + Integer.toHexString(mActivePasswordQuality)
    483                     + " does not match actual quality 0x"
    484                     + Integer.toHexString(utils.getActivePasswordQuality()));
    485             mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
    486             mActivePasswordLength = 0;
    487         }
    488 
    489         validatePasswordOwnerLocked();
    490 
    491         long timeMs = getMaximumTimeToLock(null);
    492         if (timeMs <= 0) {
    493             timeMs = Integer.MAX_VALUE;
    494         }
    495         try {
    496             getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
    497         } catch (RemoteException e) {
    498             Slog.w(TAG, "Failure talking with power manager", e);
    499         }
    500     }
    501 
    502     static void validateQualityConstant(int quality) {
    503         switch (quality) {
    504             case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
    505             case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
    506             case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
    507             case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
    508             case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
    509                 return;
    510         }
    511         throw new IllegalArgumentException("Invalid quality constant: 0x"
    512                 + Integer.toHexString(quality));
    513     }
    514 
    515     void validatePasswordOwnerLocked() {
    516         if (mPasswordOwner >= 0) {
    517             boolean haveOwner = false;
    518             for (int i=mAdminList.size()-1; i>=0; i--) {
    519                 if (mAdminList.get(i).getUid() == mPasswordOwner) {
    520                     haveOwner = true;
    521                     break;
    522                 }
    523             }
    524             if (!haveOwner) {
    525                 Slog.w(TAG, "Previous password owner " + mPasswordOwner
    526                         + " no longer active; disabling");
    527                 mPasswordOwner = -1;
    528             }
    529         }
    530     }
    531 
    532     public void systemReady() {
    533         synchronized (this) {
    534             loadSettingsLocked();
    535         }
    536     }
    537 
    538     public void setActiveAdmin(ComponentName adminReceiver) {
    539         mContext.enforceCallingOrSelfPermission(
    540                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
    541 
    542         DeviceAdminInfo info = findAdmin(adminReceiver);
    543         if (info == null) {
    544             throw new IllegalArgumentException("Bad admin: " + adminReceiver);
    545         }
    546         synchronized (this) {
    547             long ident = Binder.clearCallingIdentity();
    548             try {
    549                 if (getActiveAdminUncheckedLocked(adminReceiver) != null) {
    550                     throw new IllegalArgumentException("Admin is already added");
    551                 }
    552                 ActiveAdmin admin = new ActiveAdmin(info);
    553                 mAdminMap.put(adminReceiver, admin);
    554                 mAdminList.add(admin);
    555                 saveSettingsLocked();
    556                 sendAdminCommandLocked(admin,
    557                         DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED);
    558             } finally {
    559                 Binder.restoreCallingIdentity(ident);
    560             }
    561         }
    562     }
    563 
    564     public boolean isAdminActive(ComponentName adminReceiver) {
    565         synchronized (this) {
    566             return getActiveAdminUncheckedLocked(adminReceiver) != null;
    567         }
    568     }
    569 
    570     public List<ComponentName> getActiveAdmins() {
    571         synchronized (this) {
    572             final int N = mAdminList.size();
    573             if (N <= 0) {
    574                 return null;
    575             }
    576             ArrayList<ComponentName> res = new ArrayList<ComponentName>(N);
    577             for (int i=0; i<N; i++) {
    578                 res.add(mAdminList.get(i).info.getComponent());
    579             }
    580             return res;
    581         }
    582     }
    583 
    584     public boolean packageHasActiveAdmins(String packageName) {
    585         synchronized (this) {
    586             final int N = mAdminList.size();
    587             for (int i=0; i<N; i++) {
    588                 if (mAdminList.get(i).info.getPackageName().equals(packageName)) {
    589                     return true;
    590                 }
    591             }
    592             return false;
    593         }
    594     }
    595 
    596     public void removeActiveAdmin(ComponentName adminReceiver) {
    597         synchronized (this) {
    598             ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
    599             if (admin == null) {
    600                 return;
    601             }
    602             if (admin.getUid() != Binder.getCallingUid()) {
    603                 mContext.enforceCallingOrSelfPermission(
    604                         android.Manifest.permission.BIND_DEVICE_ADMIN, null);
    605             }
    606             long ident = Binder.clearCallingIdentity();
    607             try {
    608                 removeActiveAdminLocked(adminReceiver);
    609             } finally {
    610                 Binder.restoreCallingIdentity(ident);
    611             }
    612         }
    613     }
    614 
    615     public void setPasswordQuality(ComponentName who, int quality) {
    616         validateQualityConstant(quality);
    617 
    618         synchronized (this) {
    619             if (who == null) {
    620                 throw new NullPointerException("ComponentName is null");
    621             }
    622             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
    623                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
    624             if (ap.passwordQuality != quality) {
    625                 ap.passwordQuality = quality;
    626                 saveSettingsLocked();
    627             }
    628         }
    629     }
    630 
    631     public int getPasswordQuality(ComponentName who) {
    632         synchronized (this) {
    633             int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
    634 
    635             if (who != null) {
    636                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
    637                 return admin != null ? admin.passwordQuality : mode;
    638             }
    639 
    640             final int N = mAdminList.size();
    641             for  (int i=0; i<N; i++) {
    642                 ActiveAdmin admin = mAdminList.get(i);
    643                 if (mode < admin.passwordQuality) {
    644                     mode = admin.passwordQuality;
    645                 }
    646             }
    647             return mode;
    648         }
    649     }
    650 
    651     public void setPasswordMinimumLength(ComponentName who, int length) {
    652         synchronized (this) {
    653             if (who == null) {
    654                 throw new NullPointerException("ComponentName is null");
    655             }
    656             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
    657                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
    658             if (ap.minimumPasswordLength != length) {
    659                 ap.minimumPasswordLength = length;
    660                 saveSettingsLocked();
    661             }
    662         }
    663     }
    664 
    665     public int getPasswordMinimumLength(ComponentName who) {
    666         synchronized (this) {
    667             int length = 0;
    668 
    669             if (who != null) {
    670                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
    671                 return admin != null ? admin.minimumPasswordLength : length;
    672             }
    673 
    674             final int N = mAdminList.size();
    675             for  (int i=0; i<N; i++) {
    676                 ActiveAdmin admin = mAdminList.get(i);
    677                 if (length < admin.minimumPasswordLength) {
    678                     length = admin.minimumPasswordLength;
    679                 }
    680             }
    681             return length;
    682         }
    683     }
    684 
    685     public boolean isActivePasswordSufficient() {
    686         synchronized (this) {
    687             // This API can only be called by an active device admin,
    688             // so try to retrieve it to check that the caller is one.
    689             getActiveAdminForCallerLocked(null,
    690                     DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
    691             return mActivePasswordQuality >= getPasswordQuality(null)
    692                     && mActivePasswordLength >= getPasswordMinimumLength(null);
    693         }
    694     }
    695 
    696     public int getCurrentFailedPasswordAttempts() {
    697         synchronized (this) {
    698             // This API can only be called by an active device admin,
    699             // so try to retrieve it to check that the caller is one.
    700             getActiveAdminForCallerLocked(null,
    701                     DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
    702             return mFailedPasswordAttempts;
    703         }
    704     }
    705 
    706     public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) {
    707         synchronized (this) {
    708             // This API can only be called by an active device admin,
    709             // so try to retrieve it to check that the caller is one.
    710             getActiveAdminForCallerLocked(who,
    711                     DeviceAdminInfo.USES_POLICY_WIPE_DATA);
    712             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
    713                     DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
    714             if (ap.maximumFailedPasswordsForWipe != num) {
    715                 ap.maximumFailedPasswordsForWipe = num;
    716                 saveSettingsLocked();
    717             }
    718         }
    719     }
    720 
    721     public int getMaximumFailedPasswordsForWipe(ComponentName who) {
    722         synchronized (this) {
    723             int count = 0;
    724 
    725             if (who != null) {
    726                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
    727                 return admin != null ? admin.maximumFailedPasswordsForWipe : count;
    728             }
    729 
    730             final int N = mAdminList.size();
    731             for  (int i=0; i<N; i++) {
    732                 ActiveAdmin admin = mAdminList.get(i);
    733                 if (count == 0) {
    734                     count = admin.maximumFailedPasswordsForWipe;
    735                 } else if (admin.maximumFailedPasswordsForWipe != 0
    736                         && count > admin.maximumFailedPasswordsForWipe) {
    737                     count = admin.maximumFailedPasswordsForWipe;
    738                 }
    739             }
    740             return count;
    741         }
    742     }
    743 
    744     public boolean resetPassword(String password, int flags) {
    745         int quality;
    746         synchronized (this) {
    747             // This API can only be called by an active device admin,
    748             // so try to retrieve it to check that the caller is one.
    749             getActiveAdminForCallerLocked(null,
    750                     DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
    751             quality = getPasswordQuality(null);
    752             if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
    753                 int realQuality = LockPatternUtils.computePasswordQuality(password);
    754                 if (realQuality < quality) {
    755                     Slog.w(TAG, "resetPassword: password quality 0x"
    756                             + Integer.toHexString(quality)
    757                             + " does not meet required quality 0x"
    758                             + Integer.toHexString(quality));
    759                     return false;
    760                 }
    761                 quality = realQuality;
    762             }
    763             int length = getPasswordMinimumLength(null);
    764             if (password.length() < length) {
    765                 Slog.w(TAG, "resetPassword: password length " + password.length()
    766                         + " does not meet required length " + length);
    767                 return false;
    768             }
    769         }
    770 
    771         int callingUid = Binder.getCallingUid();
    772         if (mPasswordOwner >= 0 && mPasswordOwner != callingUid) {
    773             Slog.w(TAG, "resetPassword: already set by another uid and not entered by user");
    774             return false;
    775         }
    776 
    777         // Don't do this with the lock held, because it is going to call
    778         // back in to the service.
    779         long ident = Binder.clearCallingIdentity();
    780         try {
    781             LockPatternUtils utils = new LockPatternUtils(mContext);
    782             utils.saveLockPassword(password, quality);
    783             synchronized (this) {
    784                 int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY)
    785                         != 0 ? callingUid : -1;
    786                 if (mPasswordOwner != newOwner) {
    787                     mPasswordOwner = newOwner;
    788                     saveSettingsLocked();
    789                 }
    790             }
    791         } finally {
    792             Binder.restoreCallingIdentity(ident);
    793         }
    794 
    795         return true;
    796     }
    797 
    798     public void setMaximumTimeToLock(ComponentName who, long timeMs) {
    799         synchronized (this) {
    800             if (who == null) {
    801                 throw new NullPointerException("ComponentName is null");
    802             }
    803             ActiveAdmin ap = getActiveAdminForCallerLocked(who,
    804                     DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
    805             if (ap.maximumTimeToUnlock != timeMs) {
    806                 ap.maximumTimeToUnlock = timeMs;
    807 
    808                 long ident = Binder.clearCallingIdentity();
    809                 try {
    810                     saveSettingsLocked();
    811 
    812                     timeMs = getMaximumTimeToLock(null);
    813                     if (timeMs <= 0) {
    814                         timeMs = Integer.MAX_VALUE;
    815                     }
    816 
    817                     try {
    818                         getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
    819                     } catch (RemoteException e) {
    820                         Slog.w(TAG, "Failure talking with power manager", e);
    821                     }
    822                 } finally {
    823                     Binder.restoreCallingIdentity(ident);
    824                 }
    825             }
    826         }
    827     }
    828 
    829     public long getMaximumTimeToLock(ComponentName who) {
    830         synchronized (this) {
    831             long time = 0;
    832 
    833             if (who != null) {
    834                 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
    835                 return admin != null ? admin.maximumTimeToUnlock : time;
    836             }
    837 
    838             final int N = mAdminList.size();
    839             for  (int i=0; i<N; i++) {
    840                 ActiveAdmin admin = mAdminList.get(i);
    841                 if (time == 0) {
    842                     time = admin.maximumTimeToUnlock;
    843                 } else if (admin.maximumTimeToUnlock != 0
    844                         && time > admin.maximumTimeToUnlock) {
    845                     time = admin.maximumTimeToUnlock;
    846                 }
    847             }
    848             return time;
    849         }
    850     }
    851 
    852     public void lockNow() {
    853         synchronized (this) {
    854             // This API can only be called by an active device admin,
    855             // so try to retrieve it to check that the caller is one.
    856             getActiveAdminForCallerLocked(null,
    857                     DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
    858             long ident = Binder.clearCallingIdentity();
    859             try {
    860                 mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(),
    861                         WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN);
    862             } catch (RemoteException e) {
    863             } finally {
    864                 Binder.restoreCallingIdentity(ident);
    865             }
    866         }
    867     }
    868 
    869     void wipeDataLocked(int flags) {
    870         if ((flags&DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0) {
    871             Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
    872             intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
    873             mWakeLock.acquire(10000);
    874             mContext.startService(intent);
    875         } else {
    876             try {
    877                 RecoverySystem.rebootWipeUserData(mContext);
    878             } catch (IOException e) {
    879                 Slog.w(TAG, "Failed requesting data wipe", e);
    880             }
    881         }
    882     }
    883 
    884     public void wipeData(int flags) {
    885         synchronized (this) {
    886             // This API can only be called by an active device admin,
    887             // so try to retrieve it to check that the caller is one.
    888             getActiveAdminForCallerLocked(null,
    889                     DeviceAdminInfo.USES_POLICY_WIPE_DATA);
    890             long ident = Binder.clearCallingIdentity();
    891             try {
    892                 wipeDataLocked(flags);
    893             } finally {
    894                 Binder.restoreCallingIdentity(ident);
    895             }
    896         }
    897     }
    898 
    899     public void getRemoveWarning(ComponentName comp, final RemoteCallback result) {
    900         mContext.enforceCallingOrSelfPermission(
    901                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
    902 
    903         synchronized (this) {
    904             ActiveAdmin admin = getActiveAdminUncheckedLocked(comp);
    905             if (admin == null) {
    906                 try {
    907                     result.sendResult(null);
    908                 } catch (RemoteException e) {
    909                 }
    910                 return;
    911             }
    912             Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
    913             intent.setComponent(admin.info.getComponent());
    914             mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
    915                 @Override
    916                 public void onReceive(Context context, Intent intent) {
    917                     try {
    918                         result.sendResult(getResultExtras(false));
    919                     } catch (RemoteException e) {
    920                     }
    921                 }
    922             }, null, Activity.RESULT_OK, null, null);
    923         }
    924     }
    925 
    926     public void setActivePasswordState(int quality, int length) {
    927         mContext.enforceCallingOrSelfPermission(
    928                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
    929 
    930         validateQualityConstant(quality);
    931 
    932         synchronized (this) {
    933             if (mActivePasswordQuality != quality || mActivePasswordLength != length
    934                     || mFailedPasswordAttempts != 0) {
    935                 long ident = Binder.clearCallingIdentity();
    936                 try {
    937                     mActivePasswordQuality = quality;
    938                     mActivePasswordLength = length;
    939                     mFailedPasswordAttempts = 0;
    940                     saveSettingsLocked();
    941                     sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
    942                             DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
    943                 } finally {
    944                     Binder.restoreCallingIdentity(ident);
    945                 }
    946             }
    947         }
    948     }
    949 
    950     public void reportFailedPasswordAttempt() {
    951         mContext.enforceCallingOrSelfPermission(
    952                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
    953 
    954         synchronized (this) {
    955             long ident = Binder.clearCallingIdentity();
    956             try {
    957                 mFailedPasswordAttempts++;
    958                 saveSettingsLocked();
    959                 int max = getMaximumFailedPasswordsForWipe(null);
    960                 if (max > 0 && mFailedPasswordAttempts >= max) {
    961                     wipeDataLocked(0);
    962                 }
    963                 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
    964                         DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
    965             } finally {
    966                 Binder.restoreCallingIdentity(ident);
    967             }
    968         }
    969     }
    970 
    971     public void reportSuccessfulPasswordAttempt() {
    972         mContext.enforceCallingOrSelfPermission(
    973                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
    974 
    975         synchronized (this) {
    976             if (mFailedPasswordAttempts != 0 || mPasswordOwner >= 0) {
    977                 long ident = Binder.clearCallingIdentity();
    978                 try {
    979                     mFailedPasswordAttempts = 0;
    980                     mPasswordOwner = -1;
    981                     saveSettingsLocked();
    982                     sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
    983                             DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
    984                 } finally {
    985                     Binder.restoreCallingIdentity(ident);
    986                 }
    987             }
    988         }
    989     }
    990 
    991     @Override
    992     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    993         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
    994                 != PackageManager.PERMISSION_GRANTED) {
    995 
    996             pw.println("Permission Denial: can't dump DevicePolicyManagerService from from pid="
    997                     + Binder.getCallingPid()
    998                     + ", uid=" + Binder.getCallingUid());
    999             return;
   1000         }
   1001 
   1002         final Printer p = new PrintWriterPrinter(pw);
   1003 
   1004         synchronized (this) {
   1005             p.println("Current Device Policy Manager state:");
   1006 
   1007             p.println("  Enabled Device Admins:");
   1008             final int N = mAdminList.size();
   1009             for (int i=0; i<N; i++) {
   1010                 ActiveAdmin ap = mAdminList.get(i);
   1011                 if (ap != null) {
   1012                     pw.print("  "); pw.print(ap.info.getComponent().flattenToShortString());
   1013                             pw.println(":");
   1014                     ap.dump("    ", pw);
   1015                 }
   1016             }
   1017 
   1018             pw.println(" ");
   1019             pw.print("  mActivePasswordQuality=0x");
   1020                     pw.println(Integer.toHexString(mActivePasswordQuality));
   1021             pw.print("  mActivePasswordLength="); pw.println(mActivePasswordLength);
   1022             pw.print("  mFailedPasswordAttempts="); pw.println(mFailedPasswordAttempts);
   1023             pw.print("  mPasswordOwner="); pw.println(mPasswordOwner);
   1024         }
   1025     }
   1026 }
   1027