DevicePolicyManagerService.java revision a15dcfaf2bc7cbd13b30db6766afe3bbaa01db97
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
17package com.android.server;
18
19import com.android.internal.content.PackageMonitor;
20import com.android.internal.util.FastXmlSerializer;
21import com.android.internal.util.JournaledFile;
22import com.android.internal.util.XmlUtils;
23import com.android.internal.widget.LockPatternUtils;
24
25import org.xmlpull.v1.XmlPullParser;
26import org.xmlpull.v1.XmlPullParserException;
27import org.xmlpull.v1.XmlSerializer;
28
29import android.app.Activity;
30import android.app.admin.DeviceAdminInfo;
31import android.app.admin.DeviceAdminReceiver;
32import android.app.admin.DevicePolicyManager;
33import android.app.admin.IDevicePolicyManager;
34import android.content.BroadcastReceiver;
35import android.content.ComponentName;
36import android.content.Context;
37import android.content.Intent;
38import android.content.pm.PackageManager;
39import android.content.pm.ResolveInfo;
40import android.content.pm.PackageManager.NameNotFoundException;
41import android.os.Binder;
42import android.os.IBinder;
43import android.os.IPowerManager;
44import android.os.RecoverySystem;
45import android.os.RemoteCallback;
46import android.os.RemoteException;
47import android.os.ServiceManager;
48import android.os.SystemClock;
49import android.util.Slog;
50import android.util.PrintWriterPrinter;
51import android.util.Printer;
52import android.util.Xml;
53import android.view.WindowManagerPolicy;
54
55import java.io.File;
56import java.io.FileDescriptor;
57import java.io.FileInputStream;
58import java.io.FileOutputStream;
59import java.io.IOException;
60import java.io.PrintWriter;
61import java.util.ArrayList;
62import java.util.HashMap;
63import java.util.List;
64
65/**
66 * Implementation of the device policy APIs.
67 */
68public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
69    static final String TAG = "DevicePolicyManagerService";
70
71    final Context mContext;
72    final MyPackageMonitor mMonitor;
73
74    IPowerManager mIPowerManager;
75
76    int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
77    int mActivePasswordLength = 0;
78    int mActivePasswordUpperCase = 0;
79    int mActivePasswordLowerCase = 0;
80    int mActivePasswordLetters = 0;
81    int mActivePasswordNumeric = 0;
82    int mActivePasswordSymbols = 0;
83    int mFailedPasswordAttempts = 0;
84
85    int mPasswordOwner = -1;
86
87    final HashMap<ComponentName, ActiveAdmin> mAdminMap
88            = new HashMap<ComponentName, ActiveAdmin>();
89    final ArrayList<ActiveAdmin> mAdminList
90            = new ArrayList<ActiveAdmin>();
91
92    static class ActiveAdmin {
93        final DeviceAdminInfo info;
94
95        int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
96        int minimumPasswordLength = 0;
97        int passwordHistoryLength = 0;
98        int minimumPasswordUpperCase = 0;
99        int minimumPasswordLowerCase = 0;
100        int minimumPasswordLetters = 1;
101        int minimumPasswordNumeric = 1;
102        int minimumPasswordSymbols = 1;
103        long maximumTimeToUnlock = 0;
104        int maximumFailedPasswordsForWipe = 0;
105
106        ActiveAdmin(DeviceAdminInfo _info) {
107            info = _info;
108        }
109
110        int getUid() { return info.getActivityInfo().applicationInfo.uid; }
111
112        void writeToXml(XmlSerializer out)
113                throws IllegalArgumentException, IllegalStateException, IOException {
114            out.startTag(null, "policies");
115            info.writePoliciesToXml(out);
116            out.endTag(null, "policies");
117            if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
118                out.startTag(null, "password-quality");
119                out.attribute(null, "value", Integer.toString(passwordQuality));
120                out.endTag(null, "password-quality");
121                if (minimumPasswordLength > 0) {
122                    out.startTag(null, "min-password-length");
123                    out.attribute(null, "value", Integer.toString(minimumPasswordLength));
124                    out.endTag(null, "min-password-length");
125                }
126                if(passwordHistoryLength > 0) {
127                    out.startTag(null, "password-history-length");
128                    out.attribute(null, "value", Integer.toString(passwordHistoryLength));
129                    out.endTag(null, "password-history-length");
130                }
131                if (minimumPasswordUpperCase > 0) {
132                    out.startTag(null, "min-password-uppercase");
133                    out.attribute(null, "value", Integer.toString(minimumPasswordUpperCase));
134                    out.endTag(null, "min-password-uppercase");
135                }
136                if (minimumPasswordLowerCase > 0) {
137                    out.startTag(null, "min-password-lowercase");
138                    out.attribute(null, "value", Integer.toString(minimumPasswordLowerCase));
139                    out.endTag(null, "min-password-lowercase");
140                }
141                if (minimumPasswordLetters > 0) {
142                    out.startTag(null, "min-password-letters");
143                    out.attribute(null, "value", Integer.toString(minimumPasswordLetters));
144                    out.endTag(null, "min-password-letters");
145                }
146                if (minimumPasswordNumeric > 0) {
147                    out.startTag(null, "min-password-numeric");
148                    out.attribute(null, "value", Integer.toString(minimumPasswordNumeric));
149                    out.endTag(null, "min-password-numeric");
150                }
151                if (minimumPasswordSymbols > 0) {
152                    out.startTag(null, "min-password-symbols");
153                    out.attribute(null, "value", Integer.toString(minimumPasswordSymbols));
154                    out.endTag(null, "min-password-symbols");
155                }
156            }
157            if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
158                out.startTag(null, "max-time-to-unlock");
159                out.attribute(null, "value", Long.toString(maximumTimeToUnlock));
160                out.endTag(null, "max-time-to-unlock");
161            }
162            if (maximumFailedPasswordsForWipe != 0) {
163                out.startTag(null, "max-failed-password-wipe");
164                out.attribute(null, "value", Integer.toString(maximumFailedPasswordsForWipe));
165                out.endTag(null, "max-failed-password-wipe");
166            }
167        }
168
169        void readFromXml(XmlPullParser parser)
170                throws XmlPullParserException, IOException {
171            int outerDepth = parser.getDepth();
172            int type;
173            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
174                   && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
175                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
176                    continue;
177                }
178                String tag = parser.getName();
179                if ("policies".equals(tag)) {
180                    info.readPoliciesFromXml(parser);
181                } else if ("password-quality".equals(tag)) {
182                    passwordQuality = Integer.parseInt(
183                            parser.getAttributeValue(null, "value"));
184                } else if ("min-password-length".equals(tag)) {
185                    minimumPasswordLength = Integer.parseInt(
186                            parser.getAttributeValue(null, "value"));
187                } else if ("password-history-length".equals(tag)) {
188                    passwordHistoryLength = Integer.parseInt(
189                            parser.getAttributeValue(null, "value"));
190                } else if ("min-password-uppercase".equals(tag)) {
191                    minimumPasswordUpperCase = Integer.parseInt(
192                            parser.getAttributeValue(null, "value"));
193                } else if ("min-password-lowercase".equals(tag)) {
194                    minimumPasswordLowerCase = Integer.parseInt(
195                            parser.getAttributeValue(null, "value"));
196                } else if ("min-password-letters".equals(tag)) {
197                    minimumPasswordLetters = Integer.parseInt(
198                            parser.getAttributeValue(null, "value"));
199                } else if ("min-password-numeric".equals(tag)) {
200                    minimumPasswordNumeric = Integer.parseInt(
201                            parser.getAttributeValue(null, "value"));
202                } else if ("min-password-symbols".equals(tag)) {
203                    minimumPasswordSymbols = Integer.parseInt(
204                            parser.getAttributeValue(null, "value"));
205                } else if ("max-time-to-unlock".equals(tag)) {
206                    maximumTimeToUnlock = Long.parseLong(
207                            parser.getAttributeValue(null, "value"));
208                } else if ("max-failed-password-wipe".equals(tag)) {
209                    maximumFailedPasswordsForWipe = Integer.parseInt(
210                            parser.getAttributeValue(null, "value"));
211                } else {
212                    Slog.w(TAG, "Unknown admin tag: " + tag);
213                }
214                XmlUtils.skipCurrentTag(parser);
215            }
216        }
217
218        void dump(String prefix, PrintWriter pw) {
219            pw.print(prefix); pw.print("uid="); pw.println(getUid());
220            pw.print(prefix); pw.println("policies:");
221            ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies();
222            if (pols != null) {
223                for (int i=0; i<pols.size(); i++) {
224                    pw.print(prefix); pw.print("  "); pw.println(pols.get(i).tag);
225                }
226            }
227            pw.print(prefix); pw.print("passwordQuality=0x");
228                    pw.println(Integer.toHexString(passwordQuality));
229            pw.print(prefix); pw.print("minimumPasswordLength=");
230                    pw.println(minimumPasswordLength);
231            pw.print(prefix); pw.print("passwordHistoryLength=");
232                    pw.println(passwordHistoryLength);
233            pw.print(prefix); pw.print("minimumPasswordUpperCase=");
234                    pw.println(minimumPasswordUpperCase);
235            pw.print(prefix); pw.print("minimumPasswordLowerCase=");
236                    pw.println(minimumPasswordLowerCase);
237            pw.print(prefix); pw.print("minimumPasswordLetters=");
238                    pw.println(minimumPasswordLetters);
239            pw.print(prefix); pw.print("minimumPasswordNumeric=");
240                    pw.println(minimumPasswordNumeric);
241            pw.print(prefix); pw.print("minimumPasswordSymbols=");
242                    pw.println(minimumPasswordSymbols);
243            pw.print(prefix); pw.print("maximumTimeToUnlock=");
244                    pw.println(maximumTimeToUnlock);
245            pw.print(prefix); pw.print("maximumFailedPasswordsForWipe=");
246                    pw.println(maximumFailedPasswordsForWipe);
247        }
248    }
249
250    class MyPackageMonitor extends PackageMonitor {
251        public void onSomePackagesChanged() {
252            synchronized (DevicePolicyManagerService.this) {
253                boolean removed = false;
254                for (int i=mAdminList.size()-1; i>=0; i--) {
255                    ActiveAdmin aa = mAdminList.get(i);
256                    int change = isPackageDisappearing(aa.info.getPackageName());
257                    if (change == PACKAGE_PERMANENT_CHANGE
258                            || change == PACKAGE_TEMPORARY_CHANGE) {
259                        Slog.w(TAG, "Admin unexpectedly uninstalled: "
260                                + aa.info.getComponent());
261                        removed = true;
262                        mAdminList.remove(i);
263                    } else if (isPackageModified(aa.info.getPackageName())) {
264                        try {
265                            mContext.getPackageManager().getReceiverInfo(
266                                    aa.info.getComponent(), 0);
267                        } catch (NameNotFoundException e) {
268                            Slog.w(TAG, "Admin package change removed component: "
269                                    + aa.info.getComponent());
270                            removed = true;
271                            mAdminList.remove(i);
272                        }
273                    }
274                }
275                if (removed) {
276                    validatePasswordOwnerLocked();
277                }
278            }
279        }
280    }
281
282    /**
283     * Instantiates the service.
284     */
285    public DevicePolicyManagerService(Context context) {
286        mContext = context;
287        mMonitor = new MyPackageMonitor();
288        mMonitor.register(context, true);
289    }
290
291    private IPowerManager getIPowerManager() {
292        if (mIPowerManager == null) {
293            IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
294            mIPowerManager = IPowerManager.Stub.asInterface(b);
295        }
296        return mIPowerManager;
297    }
298
299    ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) {
300        ActiveAdmin admin = mAdminMap.get(who);
301        if (admin != null
302                && who.getPackageName().equals(admin.info.getActivityInfo().packageName)
303                && who.getClassName().equals(admin.info.getActivityInfo().name)) {
304            return admin;
305        }
306        return null;
307    }
308
309    ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
310            throws SecurityException {
311        final int callingUid = Binder.getCallingUid();
312        if (who != null) {
313            ActiveAdmin admin = mAdminMap.get(who);
314            if (admin == null) {
315                throw new SecurityException("No active admin " + who);
316            }
317            if (admin.getUid() != callingUid) {
318                throw new SecurityException("Admin " + who + " is not owned by uid "
319                        + Binder.getCallingUid());
320            }
321            if (!admin.info.usesPolicy(reqPolicy)) {
322                throw new SecurityException("Admin " + admin.info.getComponent()
323                        + " did not specify uses-policy for: "
324                        + admin.info.getTagForPolicy(reqPolicy));
325            }
326            return admin;
327        } else {
328            final int N = mAdminList.size();
329            for (int i=0; i<N; i++) {
330                ActiveAdmin admin = mAdminList.get(i);
331                if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) {
332                    return admin;
333                }
334            }
335            throw new SecurityException("No active admin owned by uid "
336                    + Binder.getCallingUid() + " for policy #" + reqPolicy);
337        }
338    }
339
340    void sendAdminCommandLocked(ActiveAdmin admin, String action) {
341        Intent intent = new Intent(action);
342        intent.setComponent(admin.info.getComponent());
343        mContext.sendBroadcast(intent);
344    }
345
346    void sendAdminCommandLocked(String action, int reqPolicy) {
347        final int N = mAdminList.size();
348        if (N > 0) {
349            for (int i=0; i<N; i++) {
350                ActiveAdmin admin = mAdminList.get(i);
351                if (admin.info.usesPolicy(reqPolicy)) {
352                    sendAdminCommandLocked(admin, action);
353                }
354            }
355        }
356    }
357
358    void removeActiveAdminLocked(ComponentName adminReceiver) {
359        ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
360        if (admin != null) {
361            sendAdminCommandLocked(admin,
362                    DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED);
363            // XXX need to wait for it to complete.
364            mAdminList.remove(admin);
365            mAdminMap.remove(adminReceiver);
366            validatePasswordOwnerLocked();
367        }
368    }
369
370    public DeviceAdminInfo findAdmin(ComponentName adminName) {
371        Intent resolveIntent = new Intent();
372        resolveIntent.setComponent(adminName);
373        List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceivers(
374                resolveIntent, PackageManager.GET_META_DATA);
375        if (infos == null || infos.size() <= 0) {
376            throw new IllegalArgumentException("Unknown admin: " + adminName);
377        }
378
379        try {
380            return new DeviceAdminInfo(mContext, infos.get(0));
381        } catch (XmlPullParserException e) {
382            Slog.w(TAG, "Bad device admin requested: " + adminName, e);
383            return null;
384        } catch (IOException e) {
385            Slog.w(TAG, "Bad device admin requested: " + adminName, e);
386            return null;
387        }
388    }
389
390    private static JournaledFile makeJournaledFile() {
391        final String base = "/data/system/device_policies.xml";
392        return new JournaledFile(new File(base), new File(base + ".tmp"));
393    }
394
395    private void saveSettingsLocked() {
396        JournaledFile journal = makeJournaledFile();
397        FileOutputStream stream = null;
398        try {
399            stream = new FileOutputStream(journal.chooseForWrite(), false);
400            XmlSerializer out = new FastXmlSerializer();
401            out.setOutput(stream, "utf-8");
402            out.startDocument(null, true);
403
404            out.startTag(null, "policies");
405
406            final int N = mAdminList.size();
407            for (int i=0; i<N; i++) {
408                ActiveAdmin ap = mAdminList.get(i);
409                if (ap != null) {
410                    out.startTag(null, "admin");
411                    out.attribute(null, "name", ap.info.getComponent().flattenToString());
412                    ap.writeToXml(out);
413                    out.endTag(null, "admin");
414                }
415            }
416
417            if (mPasswordOwner >= 0) {
418                out.startTag(null, "password-owner");
419                out.attribute(null, "value", Integer.toString(mPasswordOwner));
420                out.endTag(null, "password-owner");
421            }
422
423            if (mFailedPasswordAttempts != 0) {
424                out.startTag(null, "failed-password-attempts");
425                out.attribute(null, "value", Integer.toString(mFailedPasswordAttempts));
426                out.endTag(null, "failed-password-attempts");
427            }
428
429            if (mActivePasswordQuality != 0 || mActivePasswordLength != 0
430                    || mActivePasswordUpperCase != 0 || mActivePasswordLowerCase != 0
431                    || mActivePasswordLetters != 0 || mActivePasswordNumeric != 0
432                    || mActivePasswordSymbols != 0) {
433                out.startTag(null, "active-password");
434                out.attribute(null, "quality", Integer.toString(mActivePasswordQuality));
435                out.attribute(null, "length", Integer.toString(mActivePasswordLength));
436                out.attribute(null, "uppercase", Integer.toString(mActivePasswordUpperCase));
437                out.attribute(null, "lowercase", Integer.toString(mActivePasswordLowerCase));
438                out.attribute(null, "letters", Integer.toString(mActivePasswordLetters));
439                out.attribute(null, "numeric", Integer
440                        .toString(mActivePasswordNumeric));
441                out.attribute(null, "symbols", Integer.toString(mActivePasswordSymbols));
442                out.endTag(null, "active-password");
443            }
444
445            out.endTag(null, "policies");
446
447            out.endDocument();
448            stream.close();
449            journal.commit();
450        } catch (IOException e) {
451            try {
452                if (stream != null) {
453                    stream.close();
454                }
455            } catch (IOException ex) {
456                // Ignore
457            }
458            journal.rollback();
459        }
460    }
461
462    private void loadSettingsLocked() {
463        JournaledFile journal = makeJournaledFile();
464        FileInputStream stream = null;
465        File file = journal.chooseForRead();
466        try {
467            stream = new FileInputStream(file);
468            XmlPullParser parser = Xml.newPullParser();
469            parser.setInput(stream, null);
470
471            int type;
472            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
473                    && type != XmlPullParser.START_TAG) {
474            }
475            String tag = parser.getName();
476            if (!"policies".equals(tag)) {
477                throw new XmlPullParserException(
478                        "Settings do not start with policies tag: found " + tag);
479            }
480            type = parser.next();
481            int outerDepth = parser.getDepth();
482            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
483                   && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
484                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
485                    continue;
486                }
487                tag = parser.getName();
488                if ("admin".equals(tag)) {
489                    String name = parser.getAttributeValue(null, "name");
490                    try {
491                        DeviceAdminInfo dai = findAdmin(
492                                ComponentName.unflattenFromString(name));
493                        if (dai != null) {
494                            ActiveAdmin ap = new ActiveAdmin(dai);
495                            ap.readFromXml(parser);
496                            mAdminMap.put(ap.info.getComponent(), ap);
497                            mAdminList.add(ap);
498                        }
499                    } catch (RuntimeException e) {
500                        Slog.w(TAG, "Failed loading admin " + name, e);
501                    }
502                } else if ("failed-password-attempts".equals(tag)) {
503                    mFailedPasswordAttempts = Integer.parseInt(
504                            parser.getAttributeValue(null, "value"));
505                    XmlUtils.skipCurrentTag(parser);
506                } else if ("password-owner".equals(tag)) {
507                    mPasswordOwner = Integer.parseInt(
508                            parser.getAttributeValue(null, "value"));
509                    XmlUtils.skipCurrentTag(parser);
510                } else if ("active-password".equals(tag)) {
511                    mActivePasswordQuality = Integer.parseInt(
512                            parser.getAttributeValue(null, "quality"));
513                    mActivePasswordLength = Integer.parseInt(
514                            parser.getAttributeValue(null, "length"));
515                    mActivePasswordUpperCase = Integer.parseInt(
516                            parser.getAttributeValue(null, "uppercase"));
517                    mActivePasswordLowerCase = Integer.parseInt(
518                            parser.getAttributeValue(null, "lowercase"));
519                    mActivePasswordLetters = Integer.parseInt(
520                            parser.getAttributeValue(null, "letters"));
521                    mActivePasswordNumeric = Integer.parseInt(
522                            parser.getAttributeValue(null, "numeric"));
523                    mActivePasswordSymbols = Integer.parseInt(
524                            parser.getAttributeValue(null, "symbols"));
525                    XmlUtils.skipCurrentTag(parser);
526                } else {
527                    Slog.w(TAG, "Unknown tag: " + tag);
528                    XmlUtils.skipCurrentTag(parser);
529                }
530            }
531        } catch (NullPointerException e) {
532            Slog.w(TAG, "failed parsing " + file + " " + e);
533        } catch (NumberFormatException e) {
534            Slog.w(TAG, "failed parsing " + file + " " + e);
535        } catch (XmlPullParserException e) {
536            Slog.w(TAG, "failed parsing " + file + " " + e);
537        } catch (IOException e) {
538            Slog.w(TAG, "failed parsing " + file + " " + e);
539        } catch (IndexOutOfBoundsException e) {
540            Slog.w(TAG, "failed parsing " + file + " " + e);
541        }
542        try {
543            if (stream != null) {
544                stream.close();
545            }
546        } catch (IOException e) {
547            // Ignore
548        }
549
550        // Validate that what we stored for the password quality matches
551        // sufficiently what is currently set.  Note that this is only
552        // a sanity check in case the two get out of sync; this should
553        // never normally happen.
554        LockPatternUtils utils = new LockPatternUtils(mContext);
555        if (utils.getActivePasswordQuality() < mActivePasswordQuality) {
556            Slog.w(TAG, "Active password quality 0x"
557                    + Integer.toHexString(mActivePasswordQuality)
558                    + " does not match actual quality 0x"
559                    + Integer.toHexString(utils.getActivePasswordQuality()));
560            mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
561            mActivePasswordLength = 0;
562            mActivePasswordUpperCase = 0;
563            mActivePasswordLowerCase = 0;
564            mActivePasswordLetters = 0;
565            mActivePasswordNumeric = 0;
566            mActivePasswordSymbols = 0;
567        }
568
569        validatePasswordOwnerLocked();
570
571        long timeMs = getMaximumTimeToLock(null);
572        if (timeMs <= 0) {
573            timeMs = Integer.MAX_VALUE;
574        }
575        try {
576            getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
577        } catch (RemoteException e) {
578            Slog.w(TAG, "Failure talking with power manager", e);
579        }
580    }
581
582    static void validateQualityConstant(int quality) {
583        switch (quality) {
584            case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
585            case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
586            case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
587            case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
588            case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
589            case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
590                return;
591        }
592        throw new IllegalArgumentException("Invalid quality constant: 0x"
593                + Integer.toHexString(quality));
594    }
595
596    void validatePasswordOwnerLocked() {
597        if (mPasswordOwner >= 0) {
598            boolean haveOwner = false;
599            for (int i=mAdminList.size()-1; i>=0; i--) {
600                if (mAdminList.get(i).getUid() == mPasswordOwner) {
601                    haveOwner = true;
602                    break;
603                }
604            }
605            if (!haveOwner) {
606                Slog.w(TAG, "Previous password owner " + mPasswordOwner
607                        + " no longer active; disabling");
608                mPasswordOwner = -1;
609            }
610        }
611    }
612
613    public void systemReady() {
614        synchronized (this) {
615            loadSettingsLocked();
616        }
617    }
618
619    public void setActiveAdmin(ComponentName adminReceiver) {
620        mContext.enforceCallingOrSelfPermission(
621                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
622
623        DeviceAdminInfo info = findAdmin(adminReceiver);
624        if (info == null) {
625            throw new IllegalArgumentException("Bad admin: " + adminReceiver);
626        }
627        synchronized (this) {
628            long ident = Binder.clearCallingIdentity();
629            try {
630                if (getActiveAdminUncheckedLocked(adminReceiver) != null) {
631                    throw new IllegalArgumentException("Admin is already added");
632                }
633                ActiveAdmin admin = new ActiveAdmin(info);
634                mAdminMap.put(adminReceiver, admin);
635                mAdminList.add(admin);
636                saveSettingsLocked();
637                sendAdminCommandLocked(admin,
638                        DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED);
639            } finally {
640                Binder.restoreCallingIdentity(ident);
641            }
642        }
643    }
644
645    public boolean isAdminActive(ComponentName adminReceiver) {
646        synchronized (this) {
647            return getActiveAdminUncheckedLocked(adminReceiver) != null;
648        }
649    }
650
651    public List<ComponentName> getActiveAdmins() {
652        synchronized (this) {
653            final int N = mAdminList.size();
654            if (N <= 0) {
655                return null;
656            }
657            ArrayList<ComponentName> res = new ArrayList<ComponentName>(N);
658            for (int i=0; i<N; i++) {
659                res.add(mAdminList.get(i).info.getComponent());
660            }
661            return res;
662        }
663    }
664
665    public boolean packageHasActiveAdmins(String packageName) {
666        synchronized (this) {
667            final int N = mAdminList.size();
668            for (int i=0; i<N; i++) {
669                if (mAdminList.get(i).info.getPackageName().equals(packageName)) {
670                    return true;
671                }
672            }
673            return false;
674        }
675    }
676
677    public void removeActiveAdmin(ComponentName adminReceiver) {
678        synchronized (this) {
679            ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
680            if (admin == null) {
681                return;
682            }
683            if (admin.getUid() != Binder.getCallingUid()) {
684                mContext.enforceCallingOrSelfPermission(
685                        android.Manifest.permission.BIND_DEVICE_ADMIN, null);
686            }
687            long ident = Binder.clearCallingIdentity();
688            try {
689                removeActiveAdminLocked(adminReceiver);
690            } finally {
691                Binder.restoreCallingIdentity(ident);
692            }
693        }
694    }
695
696    public void setPasswordQuality(ComponentName who, int quality) {
697        validateQualityConstant(quality);
698
699        synchronized (this) {
700            if (who == null) {
701                throw new NullPointerException("ComponentName is null");
702            }
703            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
704                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
705            if (ap.passwordQuality != quality) {
706                ap.passwordQuality = quality;
707                saveSettingsLocked();
708            }
709        }
710    }
711
712    public int getPasswordQuality(ComponentName who) {
713        synchronized (this) {
714            int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
715
716            if (who != null) {
717                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
718                return admin != null ? admin.passwordQuality : mode;
719            }
720
721            final int N = mAdminList.size();
722            for  (int i=0; i<N; i++) {
723                ActiveAdmin admin = mAdminList.get(i);
724                if (mode < admin.passwordQuality) {
725                    mode = admin.passwordQuality;
726                }
727            }
728            return mode;
729        }
730    }
731
732    public void setPasswordMinimumLength(ComponentName who, int length) {
733        synchronized (this) {
734            if (who == null) {
735                throw new NullPointerException("ComponentName is null");
736            }
737            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
738                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
739            if (ap.minimumPasswordLength != length) {
740                ap.minimumPasswordLength = length;
741                saveSettingsLocked();
742            }
743        }
744    }
745
746    public int getPasswordMinimumLength(ComponentName who) {
747        synchronized (this) {
748            int length = 0;
749
750            if (who != null) {
751                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
752                return admin != null ? admin.minimumPasswordLength : length;
753            }
754
755            final int N = mAdminList.size();
756            for  (int i=0; i<N; i++) {
757                ActiveAdmin admin = mAdminList.get(i);
758                if (length < admin.minimumPasswordLength) {
759                    length = admin.minimumPasswordLength;
760                }
761            }
762            return length;
763        }
764    }
765
766    public void setPasswordHistoryLength(ComponentName who, int length) {
767        synchronized (this) {
768            if (who == null) {
769                throw new NullPointerException("ComponentName is null");
770            }
771            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
772                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
773            if (ap.passwordHistoryLength != length) {
774                ap.passwordHistoryLength = length;
775                saveSettingsLocked();
776            }
777        }
778    }
779
780    public int getPasswordHistoryLength(ComponentName who) {
781        synchronized (this) {
782            int length = 0;
783
784            if (who != null) {
785                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
786                return admin != null ? admin.passwordHistoryLength : length;
787            }
788
789            final int N = mAdminList.size();
790            for (int i = 0; i < N; i++) {
791                ActiveAdmin admin = mAdminList.get(i);
792                if (length < admin.passwordHistoryLength) {
793                    length = admin.passwordHistoryLength;
794                }
795            }
796            return length;
797        }
798    }
799
800    public void setPasswordMinimumUpperCase(ComponentName who, int length) {
801        synchronized (this) {
802            if (who == null) {
803                throw new NullPointerException("ComponentName is null");
804            }
805            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
806                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
807            if (ap.minimumPasswordUpperCase != length) {
808                ap.minimumPasswordUpperCase = length;
809                saveSettingsLocked();
810            }
811        }
812    }
813
814    public int getPasswordMinimumUpperCase(ComponentName who) {
815        synchronized (this) {
816            int length = 0;
817
818            if (who != null) {
819                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
820                return admin != null ? admin.minimumPasswordUpperCase : length;
821            }
822
823            final int N = mAdminList.size();
824            for (int i=0; i<N; i++) {
825                ActiveAdmin admin = mAdminList.get(i);
826                if (length < admin.minimumPasswordUpperCase) {
827                    length = admin.minimumPasswordUpperCase;
828                }
829            }
830            return length;
831        }
832    }
833
834    public void setPasswordMinimumLowerCase(ComponentName who, int length) {
835        synchronized (this) {
836            if (who == null) {
837                throw new NullPointerException("ComponentName is null");
838            }
839            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
840                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
841            if (ap.minimumPasswordLowerCase != length) {
842                ap.minimumPasswordLowerCase = length;
843                saveSettingsLocked();
844            }
845        }
846    }
847
848    public int getPasswordMinimumLowerCase(ComponentName who) {
849        synchronized (this) {
850            int length = 0;
851
852            if (who != null) {
853                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
854                return admin != null ? admin.minimumPasswordLowerCase : length;
855            }
856
857            final int N = mAdminList.size();
858            for (int i=0; i<N; i++) {
859                ActiveAdmin admin = mAdminList.get(i);
860                if (length < admin.minimumPasswordLowerCase) {
861                    length = admin.minimumPasswordLowerCase;
862                }
863            }
864            return length;
865        }
866    }
867
868    public void setPasswordMinimumLetters(ComponentName who, int length) {
869        synchronized (this) {
870            if (who == null) {
871                throw new NullPointerException("ComponentName is null");
872            }
873            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
874                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
875            if (ap.minimumPasswordLetters != length) {
876                ap.minimumPasswordLetters = length;
877                saveSettingsLocked();
878            }
879        }
880    }
881
882    public int getPasswordMinimumLetters(ComponentName who) {
883        synchronized (this) {
884            int length = 0;
885
886            if (who != null) {
887                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
888                return admin != null ? admin.minimumPasswordLetters : length;
889            }
890
891            final int N = mAdminList.size();
892            for (int i=0; i<N; i++) {
893                ActiveAdmin admin = mAdminList.get(i);
894                if (length < admin.minimumPasswordLetters) {
895                    length = admin.minimumPasswordLetters;
896                }
897            }
898            return length;
899        }
900    }
901
902    public void setPasswordMinimumNumeric(ComponentName who, int length) {
903        synchronized (this) {
904            if (who == null) {
905                throw new NullPointerException("ComponentName is null");
906            }
907            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
908                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
909            if (ap.minimumPasswordNumeric != length) {
910                ap.minimumPasswordNumeric = length;
911                saveSettingsLocked();
912            }
913        }
914    }
915
916    public int getPasswordMinimumNumeric(ComponentName who) {
917        synchronized (this) {
918            int length = 0;
919
920            if (who != null) {
921                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
922                return admin != null ? admin.minimumPasswordNumeric : length;
923            }
924
925            final int N = mAdminList.size();
926            for (int i = 0; i < N; i++) {
927                ActiveAdmin admin = mAdminList.get(i);
928                if (length < admin.minimumPasswordNumeric) {
929                    length = admin.minimumPasswordNumeric;
930                }
931            }
932            return length;
933        }
934    }
935
936    public void setPasswordMinimumSymbols(ComponentName who, int length) {
937        synchronized (this) {
938            if (who == null) {
939                throw new NullPointerException("ComponentName is null");
940            }
941            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
942                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
943            if (ap.minimumPasswordSymbols != length) {
944                ap.minimumPasswordSymbols = length;
945                saveSettingsLocked();
946            }
947        }
948    }
949
950    public int getPasswordMinimumSymbols(ComponentName who) {
951        synchronized (this) {
952            int length = 0;
953
954            if (who != null) {
955                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
956                return admin != null ? admin.minimumPasswordSymbols : length;
957            }
958
959            final int N = mAdminList.size();
960            for  (int i=0; i<N; i++) {
961                ActiveAdmin admin = mAdminList.get(i);
962                if (length < admin.minimumPasswordSymbols) {
963                    length = admin.minimumPasswordSymbols;
964                }
965            }
966            return length;
967        }
968    }
969
970    public boolean isActivePasswordSufficient() {
971        synchronized (this) {
972            // This API can only be called by an active device admin,
973            // so try to retrieve it to check that the caller is one.
974            getActiveAdminForCallerLocked(null,
975                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
976            if (mActivePasswordQuality < getPasswordQuality(null)
977                    || mActivePasswordLength < getPasswordMinimumLength(null)) {
978                return false;
979            }
980            if(mActivePasswordQuality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
981                return true;
982            }
983            return mActivePasswordUpperCase >= getPasswordMinimumUpperCase(null)
984                    && mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null)
985                    && mActivePasswordLetters >= getPasswordMinimumLetters(null)
986                    && mActivePasswordNumeric >= getPasswordMinimumNumeric(null)
987                    && mActivePasswordSymbols >= getPasswordMinimumSymbols(null);
988        }
989    }
990
991    public int getCurrentFailedPasswordAttempts() {
992        synchronized (this) {
993            // This API can only be called by an active device admin,
994            // so try to retrieve it to check that the caller is one.
995            getActiveAdminForCallerLocked(null,
996                    DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
997            return mFailedPasswordAttempts;
998        }
999    }
1000
1001    public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) {
1002        synchronized (this) {
1003            // This API can only be called by an active device admin,
1004            // so try to retrieve it to check that the caller is one.
1005            getActiveAdminForCallerLocked(who,
1006                    DeviceAdminInfo.USES_POLICY_WIPE_DATA);
1007            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
1008                    DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
1009            if (ap.maximumFailedPasswordsForWipe != num) {
1010                ap.maximumFailedPasswordsForWipe = num;
1011                saveSettingsLocked();
1012            }
1013        }
1014    }
1015
1016    public int getMaximumFailedPasswordsForWipe(ComponentName who) {
1017        synchronized (this) {
1018            int count = 0;
1019
1020            if (who != null) {
1021                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
1022                return admin != null ? admin.maximumFailedPasswordsForWipe : count;
1023            }
1024
1025            final int N = mAdminList.size();
1026            for  (int i=0; i<N; i++) {
1027                ActiveAdmin admin = mAdminList.get(i);
1028                if (count == 0) {
1029                    count = admin.maximumFailedPasswordsForWipe;
1030                } else if (admin.maximumFailedPasswordsForWipe != 0
1031                        && count > admin.maximumFailedPasswordsForWipe) {
1032                    count = admin.maximumFailedPasswordsForWipe;
1033                }
1034            }
1035            return count;
1036        }
1037    }
1038
1039    public boolean resetPassword(String password, int flags) {
1040        int quality;
1041        synchronized (this) {
1042            // This API can only be called by an active device admin,
1043            // so try to retrieve it to check that the caller is one.
1044            getActiveAdminForCallerLocked(null,
1045                    DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
1046            quality = getPasswordQuality(null);
1047            if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
1048                int realQuality = LockPatternUtils.computePasswordQuality(password);
1049                if (realQuality < quality
1050                        && quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
1051                    Slog.w(TAG, "resetPassword: password quality 0x"
1052                            + Integer.toHexString(quality)
1053                            + " does not meet required quality 0x"
1054                            + Integer.toHexString(quality));
1055                    return false;
1056                }
1057                quality = Math.max(realQuality, quality);
1058            }
1059            int length = getPasswordMinimumLength(null);
1060            if (password.length() < length) {
1061                Slog.w(TAG, "resetPassword: password length " + password.length()
1062                        + " does not meet required length " + length);
1063                return false;
1064            }
1065            if (quality == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
1066                int letters = 0;
1067                int uppercase = 0;
1068                int lowercase = 0;
1069                int numbers = 0;
1070                int symbols = 0;
1071                for (int i = 0; i < password.length(); i++) {
1072                    char c = password.charAt(i);
1073                    if (c >= 'A' && c <= 'Z') {
1074                        letters++;
1075                        uppercase++;
1076                    } else if (c >= 'a' && c <= 'z') {
1077                        letters++;
1078                        lowercase++;
1079                    } else if (c >= '0' && c <= '9') {
1080                        numbers++;
1081                    } else {
1082                        symbols++;
1083                    }
1084                }
1085                int neededLetters = getPasswordMinimumLetters(null);
1086                if(letters < neededLetters) {
1087                    Slog.w(TAG, "resetPassword: number of letters " + letters
1088                            + " does not meet required number of letters " + neededLetters);
1089                    return false;
1090                }
1091                int neededNumbers = getPasswordMinimumNumeric(null);
1092                if (numbers < neededNumbers) {
1093                    Slog
1094                            .w(TAG, "resetPassword: number of numerical digits " + numbers
1095                                    + " does not meet required number of numerical digits "
1096                                    + neededNumbers);
1097                    return false;
1098                }
1099                int neededLowerCase = getPasswordMinimumLowerCase(null);
1100                if (lowercase < neededLowerCase) {
1101                    Slog.w(TAG, "resetPassword: number of lowercase letters " + lowercase
1102                            + " does not meet required number of lowercase letters "
1103                            + neededLowerCase);
1104                    return false;
1105                }
1106                int neededUpperCase = getPasswordMinimumUpperCase(null);
1107                if (uppercase < neededUpperCase) {
1108                    Slog.w(TAG, "resetPassword: number of uppercase letters " + uppercase
1109                            + " does not meet required number of uppercase letters "
1110                            + neededUpperCase);
1111                    return false;
1112                }
1113                int neededSymbols = getPasswordMinimumSymbols(null);
1114                if (symbols < neededSymbols) {
1115                    Slog.w(TAG, "resetPassword: number of special symbols " + symbols
1116                            + " does not meet required number of special symbols " + neededSymbols);
1117                    return false;
1118                }
1119            }
1120
1121            LockPatternUtils utils = new LockPatternUtils(mContext);
1122            if(utils.checkPasswordHistory(password)) {
1123                Slog.w(TAG, "resetPassword: password is the same as one of the last "
1124                        + getPasswordHistoryLength(null) + " passwords");
1125                return false;
1126            }
1127        }
1128
1129        int callingUid = Binder.getCallingUid();
1130        if (mPasswordOwner >= 0 && mPasswordOwner != callingUid) {
1131            Slog.w(TAG, "resetPassword: already set by another uid and not entered by user");
1132            return false;
1133        }
1134
1135        // Don't do this with the lock held, because it is going to call
1136        // back in to the service.
1137        long ident = Binder.clearCallingIdentity();
1138        try {
1139            LockPatternUtils utils = new LockPatternUtils(mContext);
1140            utils.saveLockPassword(password, quality);
1141            synchronized (this) {
1142                int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY)
1143                        != 0 ? callingUid : -1;
1144                if (mPasswordOwner != newOwner) {
1145                    mPasswordOwner = newOwner;
1146                    saveSettingsLocked();
1147                }
1148            }
1149        } finally {
1150            Binder.restoreCallingIdentity(ident);
1151        }
1152
1153        return true;
1154    }
1155
1156    public void setMaximumTimeToLock(ComponentName who, long timeMs) {
1157        synchronized (this) {
1158            if (who == null) {
1159                throw new NullPointerException("ComponentName is null");
1160            }
1161            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
1162                    DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
1163            if (ap.maximumTimeToUnlock != timeMs) {
1164                ap.maximumTimeToUnlock = timeMs;
1165
1166                long ident = Binder.clearCallingIdentity();
1167                try {
1168                    saveSettingsLocked();
1169
1170                    timeMs = getMaximumTimeToLock(null);
1171                    if (timeMs <= 0) {
1172                        timeMs = Integer.MAX_VALUE;
1173                    }
1174
1175                    try {
1176                        getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
1177                    } catch (RemoteException e) {
1178                        Slog.w(TAG, "Failure talking with power manager", e);
1179                    }
1180                } finally {
1181                    Binder.restoreCallingIdentity(ident);
1182                }
1183            }
1184        }
1185    }
1186
1187    public long getMaximumTimeToLock(ComponentName who) {
1188        synchronized (this) {
1189            long time = 0;
1190
1191            if (who != null) {
1192                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
1193                return admin != null ? admin.maximumTimeToUnlock : time;
1194            }
1195
1196            final int N = mAdminList.size();
1197            for  (int i=0; i<N; i++) {
1198                ActiveAdmin admin = mAdminList.get(i);
1199                if (time == 0) {
1200                    time = admin.maximumTimeToUnlock;
1201                } else if (admin.maximumTimeToUnlock != 0
1202                        && time > admin.maximumTimeToUnlock) {
1203                    time = admin.maximumTimeToUnlock;
1204                }
1205            }
1206            return time;
1207        }
1208    }
1209
1210    public void lockNow() {
1211        synchronized (this) {
1212            // This API can only be called by an active device admin,
1213            // so try to retrieve it to check that the caller is one.
1214            getActiveAdminForCallerLocked(null,
1215                    DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
1216            long ident = Binder.clearCallingIdentity();
1217            try {
1218                mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(),
1219                        WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN);
1220            } catch (RemoteException e) {
1221            } finally {
1222                Binder.restoreCallingIdentity(ident);
1223            }
1224        }
1225    }
1226
1227    void wipeDataLocked(int flags) {
1228        try {
1229            RecoverySystem.rebootWipeUserData(mContext);
1230        } catch (IOException e) {
1231            Slog.w(TAG, "Failed requesting data wipe", e);
1232        }
1233    }
1234
1235    public void wipeData(int flags) {
1236        synchronized (this) {
1237            // This API can only be called by an active device admin,
1238            // so try to retrieve it to check that the caller is one.
1239            getActiveAdminForCallerLocked(null,
1240                    DeviceAdminInfo.USES_POLICY_WIPE_DATA);
1241            long ident = Binder.clearCallingIdentity();
1242            try {
1243                wipeDataLocked(flags);
1244            } finally {
1245                Binder.restoreCallingIdentity(ident);
1246            }
1247        }
1248    }
1249
1250    public void getRemoveWarning(ComponentName comp, final RemoteCallback result) {
1251        mContext.enforceCallingOrSelfPermission(
1252                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
1253
1254        synchronized (this) {
1255            ActiveAdmin admin = getActiveAdminUncheckedLocked(comp);
1256            if (admin == null) {
1257                try {
1258                    result.sendResult(null);
1259                } catch (RemoteException e) {
1260                }
1261                return;
1262            }
1263            Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
1264            intent.setComponent(admin.info.getComponent());
1265            mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
1266                @Override
1267                public void onReceive(Context context, Intent intent) {
1268                    try {
1269                        result.sendResult(getResultExtras(false));
1270                    } catch (RemoteException e) {
1271                    }
1272                }
1273            }, null, Activity.RESULT_OK, null, null);
1274        }
1275    }
1276
1277    public void setActivePasswordState(int quality, int length, int letters, int uppercase,
1278            int lowercase, int numbers, int symbols) {
1279        mContext.enforceCallingOrSelfPermission(
1280                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
1281
1282        validateQualityConstant(quality);
1283
1284        synchronized (this) {
1285            if (mActivePasswordQuality != quality || mActivePasswordLength != length
1286                    || mFailedPasswordAttempts != 0 || mActivePasswordLetters != letters
1287                    || mActivePasswordUpperCase != uppercase
1288                    || mActivePasswordLowerCase != lowercase || mActivePasswordNumeric != numbers
1289                    || mActivePasswordSymbols != symbols) {
1290                long ident = Binder.clearCallingIdentity();
1291                try {
1292                    mActivePasswordQuality = quality;
1293                    mActivePasswordLength = length;
1294                    mActivePasswordLetters = letters;
1295                    mActivePasswordLowerCase = lowercase;
1296                    mActivePasswordUpperCase = uppercase;
1297                    mActivePasswordNumeric = numbers;
1298                    mActivePasswordSymbols = symbols;
1299                    mFailedPasswordAttempts = 0;
1300                    saveSettingsLocked();
1301                    sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
1302                            DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
1303                } finally {
1304                    Binder.restoreCallingIdentity(ident);
1305                }
1306            }
1307        }
1308    }
1309
1310    public void reportFailedPasswordAttempt() {
1311        mContext.enforceCallingOrSelfPermission(
1312                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
1313
1314        synchronized (this) {
1315            long ident = Binder.clearCallingIdentity();
1316            try {
1317                mFailedPasswordAttempts++;
1318                saveSettingsLocked();
1319                int max = getMaximumFailedPasswordsForWipe(null);
1320                if (max > 0 && mFailedPasswordAttempts >= max) {
1321                    wipeDataLocked(0);
1322                }
1323                sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
1324                        DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
1325            } finally {
1326                Binder.restoreCallingIdentity(ident);
1327            }
1328        }
1329    }
1330
1331    public void reportSuccessfulPasswordAttempt() {
1332        mContext.enforceCallingOrSelfPermission(
1333                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
1334
1335        synchronized (this) {
1336            if (mFailedPasswordAttempts != 0 || mPasswordOwner >= 0) {
1337                long ident = Binder.clearCallingIdentity();
1338                try {
1339                    mFailedPasswordAttempts = 0;
1340                    mPasswordOwner = -1;
1341                    saveSettingsLocked();
1342                    sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
1343                            DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
1344                } finally {
1345                    Binder.restoreCallingIdentity(ident);
1346                }
1347            }
1348        }
1349    }
1350
1351    @Override
1352    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1353        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1354                != PackageManager.PERMISSION_GRANTED) {
1355
1356            pw.println("Permission Denial: can't dump DevicePolicyManagerService from from pid="
1357                    + Binder.getCallingPid()
1358                    + ", uid=" + Binder.getCallingUid());
1359            return;
1360        }
1361
1362        final Printer p = new PrintWriterPrinter(pw);
1363
1364        synchronized (this) {
1365            p.println("Current Device Policy Manager state:");
1366
1367            p.println("  Enabled Device Admins:");
1368            final int N = mAdminList.size();
1369            for (int i=0; i<N; i++) {
1370                ActiveAdmin ap = mAdminList.get(i);
1371                if (ap != null) {
1372                    pw.print("  "); pw.print(ap.info.getComponent().flattenToShortString());
1373                            pw.println(":");
1374                    ap.dump("    ", pw);
1375                }
1376            }
1377
1378            pw.println(" ");
1379            pw.print("  mActivePasswordQuality=0x");
1380                    pw.println(Integer.toHexString(mActivePasswordQuality));
1381            pw.print("  mActivePasswordLength="); pw.println(mActivePasswordLength);
1382            pw.print("  mActivePasswordUpperCase="); pw.println(mActivePasswordUpperCase);
1383            pw.print("  mActivePasswordLowerCase="); pw.println(mActivePasswordLowerCase);
1384            pw.print("  mActivePasswordLetters="); pw.println(mActivePasswordLetters);
1385            pw.print("  mActivePasswordNumeric="); pw.println(mActivePasswordNumeric);
1386            pw.print("  mActivePasswordSymbols="); pw.println(mActivePasswordSymbols);
1387            pw.print("  mFailedPasswordAttempts="); pw.println(mFailedPasswordAttempts);
1388            pw.print("  mPasswordOwner="); pw.println(mPasswordOwner);
1389        }
1390    }
1391}
1392