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