DevicePolicyManagerService.java revision 21f1bd17b2dfe361acbb28453b3f3b1a110932fa
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.common.FastXmlSerializer;
20import com.android.common.XmlUtils;
21import com.android.internal.content.PackageMonitor;
22import com.android.internal.widget.LockPatternUtils;
23
24import org.xmlpull.v1.XmlPullParser;
25import org.xmlpull.v1.XmlPullParserException;
26import org.xmlpull.v1.XmlSerializer;
27
28import android.app.Activity;
29import android.app.DeviceAdminReceiver;
30import android.app.DeviceAdminInfo;
31import android.app.DevicePolicyManager;
32import android.app.IDevicePolicyManager;
33import android.content.BroadcastReceiver;
34import android.content.ComponentName;
35import android.content.Context;
36import android.content.Intent;
37import android.content.pm.PackageManager;
38import android.content.pm.ResolveInfo;
39import android.content.pm.PackageManager.NameNotFoundException;
40import android.os.Binder;
41import android.os.IBinder;
42import android.os.IPowerManager;
43import android.os.RecoverySystem;
44import android.os.RemoteCallback;
45import android.os.RemoteException;
46import android.os.ServiceManager;
47import android.os.SystemClock;
48import android.util.Log;
49import android.util.Xml;
50import android.view.WindowManagerPolicy;
51
52import java.io.File;
53import java.io.FileInputStream;
54import java.io.FileOutputStream;
55import java.io.IOException;
56import java.util.ArrayList;
57import java.util.HashMap;
58import java.util.List;
59
60/**
61 * Implementation of the device policy APIs.
62 */
63public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
64    static final String TAG = "DevicePolicyManagerService";
65
66    final Context mContext;
67    final MyPackageMonitor mMonitor;
68
69    IPowerManager mIPowerManager;
70
71    int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
72    int mActivePasswordLength = 0;
73    int mFailedPasswordAttempts = 0;
74
75    final HashMap<ComponentName, ActiveAdmin> mAdminMap
76            = new HashMap<ComponentName, ActiveAdmin>();
77    final ArrayList<ActiveAdmin> mAdminList
78            = new ArrayList<ActiveAdmin>();
79
80    static class ActiveAdmin {
81        final DeviceAdminInfo info;
82
83        int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
84        int minimumPasswordLength = 0;
85        long maximumTimeToUnlock = 0;
86        int maximumFailedPasswordsForWipe = 0;
87
88        ActiveAdmin(DeviceAdminInfo _info) {
89            info = _info;
90        }
91
92        int getUid() { return info.getActivityInfo().applicationInfo.uid; }
93
94        void writeToXml(XmlSerializer out)
95                throws IllegalArgumentException, IllegalStateException, IOException {
96            out.startTag(null, "policies");
97            info.writePoliciesToXml(out);
98            out.endTag(null, "policies");
99            if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
100                out.startTag(null, "password-quality");
101                out.attribute(null, "value", Integer.toString(passwordQuality));
102                out.endTag(null, "password-quality");
103                if (minimumPasswordLength > 0) {
104                    out.startTag(null, "min-password-length");
105                    out.attribute(null, "value", Integer.toString(minimumPasswordLength));
106                    out.endTag(null, "mn-password-length");
107                }
108            }
109            if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
110                out.startTag(null, "max-time-to-unlock");
111                out.attribute(null, "value", Long.toString(maximumTimeToUnlock));
112                out.endTag(null, "max-time-to-unlock");
113            }
114            if (maximumFailedPasswordsForWipe != 0) {
115                out.startTag(null, "max-failed-password-wipe");
116                out.attribute(null, "value", Integer.toString(maximumFailedPasswordsForWipe));
117                out.endTag(null, "max-failed-password-wipe");
118            }
119        }
120
121        void readFromXml(XmlPullParser parser)
122                throws XmlPullParserException, IOException {
123            int outerDepth = parser.getDepth();
124            int type;
125            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
126                   && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
127                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
128                    continue;
129                }
130                String tag = parser.getName();
131                if ("policies".equals(tag)) {
132                    info.readPoliciesFromXml(parser);
133                } else if ("password-quality".equals(tag)) {
134                    passwordQuality = Integer.parseInt(
135                            parser.getAttributeValue(null, "value"));
136                } else if ("min-password-length".equals(tag)) {
137                    minimumPasswordLength = Integer.parseInt(
138                            parser.getAttributeValue(null, "value"));
139                } else if ("max-time-to-unlock".equals(tag)) {
140                    maximumTimeToUnlock = Long.parseLong(
141                            parser.getAttributeValue(null, "value"));
142                } else if ("max-failed-password-wipe".equals(tag)) {
143                    maximumFailedPasswordsForWipe = Integer.parseInt(
144                            parser.getAttributeValue(null, "value"));
145                } else {
146                    Log.w(TAG, "Unknown admin tag: " + tag);
147                }
148                XmlUtils.skipCurrentTag(parser);
149            }
150        }
151    }
152
153    class MyPackageMonitor extends PackageMonitor {
154        public void onSomePackagesChanged() {
155            synchronized (DevicePolicyManagerService.this) {
156                for (int i=mAdminList.size()-1; i>=0; i--) {
157                    ActiveAdmin aa = mAdminList.get(i);
158                    int change = isPackageDisappearing(aa.info.getPackageName());
159                    if (change == PACKAGE_PERMANENT_CHANGE
160                            || change == PACKAGE_TEMPORARY_CHANGE) {
161                        Log.w(TAG, "Admin unexpectedly uninstalled: "
162                                + aa.info.getComponent());
163                        mAdminList.remove(i);
164                    } else if (isPackageModified(aa.info.getPackageName())) {
165                        try {
166                            mContext.getPackageManager().getReceiverInfo(
167                                    aa.info.getComponent(), 0);
168                        } catch (NameNotFoundException e) {
169                            Log.w(TAG, "Admin package change removed component: "
170                                    + aa.info.getComponent());
171                            mAdminList.remove(i);
172                        }
173                    }
174                }
175            }
176        }
177    }
178
179    /**
180     * Instantiates the service.
181     */
182    public DevicePolicyManagerService(Context context) {
183        mContext = context;
184        mMonitor = new MyPackageMonitor();
185        mMonitor.register(context, true);
186    }
187
188    private IPowerManager getIPowerManager() {
189        if (mIPowerManager == null) {
190            IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
191            mIPowerManager = IPowerManager.Stub.asInterface(b);
192        }
193        return mIPowerManager;
194    }
195
196    ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) {
197        ActiveAdmin admin = mAdminMap.get(who);
198        if (admin != null
199                && who.getPackageName().equals(admin.info.getActivityInfo().packageName)
200                && who.getClassName().equals(admin.info.getActivityInfo().name)) {
201            return admin;
202        }
203        return null;
204    }
205
206    ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
207            throws SecurityException {
208        final int callingUid = Binder.getCallingUid();
209        if (who != null) {
210            ActiveAdmin admin = mAdminMap.get(who);
211            if (admin == null) {
212                throw new SecurityException("No active admin " + who);
213            }
214            if (admin.getUid() != callingUid) {
215                throw new SecurityException("Admin " + who + " is not owned by uid "
216                        + Binder.getCallingUid());
217            }
218            if (!admin.info.usesPolicy(reqPolicy)) {
219                throw new SecurityException("Admin " + admin.info.getComponent()
220                        + " did not specify uses-policy for: "
221                        + admin.info.getTagForPolicy(reqPolicy));
222            }
223            return admin;
224        } else {
225            final int N = mAdminList.size();
226            for (int i=0; i<N; i++) {
227                ActiveAdmin admin = mAdminList.get(i);
228                if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) {
229                    return admin;
230                }
231            }
232            throw new SecurityException("No active admin owned by uid "
233                    + Binder.getCallingUid() + " for policy #" + reqPolicy);
234        }
235    }
236
237    void sendAdminCommandLocked(ActiveAdmin admin, String action) {
238        Intent intent = new Intent(action);
239        intent.setComponent(admin.info.getComponent());
240        mContext.sendBroadcast(intent);
241    }
242
243    void sendAdminCommandLocked(String action, int reqPolicy) {
244        final int N = mAdminList.size();
245        if (N > 0) {
246            for (int i=0; i<N; i++) {
247                ActiveAdmin admin = mAdminList.get(i);
248                if (admin.info.usesPolicy(reqPolicy)) {
249                    sendAdminCommandLocked(admin, action);
250                }
251            }
252        }
253    }
254
255    void removeActiveAdminLocked(ComponentName adminReceiver) {
256        ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
257        if (admin != null) {
258            sendAdminCommandLocked(admin,
259                    DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED);
260            // XXX need to wait for it to complete.
261            mAdminList.remove(admin);
262            mAdminMap.remove(adminReceiver);
263        }
264    }
265
266    public DeviceAdminInfo findAdmin(ComponentName adminName) {
267        Intent resolveIntent = new Intent();
268        resolveIntent.setComponent(adminName);
269        List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceivers(
270                resolveIntent, PackageManager.GET_META_DATA);
271        if (infos == null || infos.size() <= 0) {
272            throw new IllegalArgumentException("Unknown admin: " + adminName);
273        }
274
275        try {
276            return new DeviceAdminInfo(mContext, infos.get(0));
277        } catch (XmlPullParserException e) {
278            Log.w(TAG, "Bad device admin requested: " + adminName, e);
279            return null;
280        } catch (IOException e) {
281            Log.w(TAG, "Bad device admin requested: " + adminName, e);
282            return null;
283        }
284    }
285
286    private static JournaledFile makeJournaledFile() {
287        final String base = "/data/system/device_policies.xml";
288        return new JournaledFile(new File(base), new File(base + ".tmp"));
289    }
290
291    private void saveSettingsLocked() {
292        JournaledFile journal = makeJournaledFile();
293        FileOutputStream stream = null;
294        try {
295            stream = new FileOutputStream(journal.chooseForWrite(), false);
296            XmlSerializer out = new FastXmlSerializer();
297            out.setOutput(stream, "utf-8");
298            out.startDocument(null, true);
299
300            out.startTag(null, "policies");
301
302            final int N = mAdminList.size();
303            for (int i=0; i<N; i++) {
304                ActiveAdmin ap = mAdminList.get(i);
305                if (ap != null) {
306                    out.startTag(null, "admin");
307                    out.attribute(null, "name", ap.info.getComponent().flattenToString());
308                    ap.writeToXml(out);
309                    out.endTag(null, "admin");
310                }
311            }
312
313            out.endTag(null, "policies");
314
315            if (mFailedPasswordAttempts != 0) {
316                out.startTag(null, "failed-password-attempts");
317                out.attribute(null, "value", Integer.toString(mFailedPasswordAttempts));
318                out.endTag(null, "failed-password-attempts");
319            }
320
321            out.endDocument();
322            stream.close();
323            journal.commit();
324        } catch (IOException e) {
325            try {
326                if (stream != null) {
327                    stream.close();
328                }
329            } catch (IOException ex) {
330                // Ignore
331            }
332            journal.rollback();
333        }
334    }
335
336    private void loadSettingsLocked() {
337        JournaledFile journal = makeJournaledFile();
338        FileInputStream stream = null;
339        File file = journal.chooseForRead();
340        try {
341            stream = new FileInputStream(file);
342            XmlPullParser parser = Xml.newPullParser();
343            parser.setInput(stream, null);
344
345            int type;
346            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
347                    && type != XmlPullParser.START_TAG) {
348            }
349            String tag = parser.getName();
350            if (!"policies".equals(tag)) {
351                throw new XmlPullParserException(
352                        "Settings do not start with policies tag: found " + tag);
353            }
354            type = parser.next();
355            int outerDepth = parser.getDepth();
356            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
357                   && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
358                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
359                    continue;
360                }
361                tag = parser.getName();
362                if ("admin".equals(tag)) {
363                    String name = parser.getAttributeValue(null, "name");
364                    try {
365                        DeviceAdminInfo dai = findAdmin(
366                                ComponentName.unflattenFromString(name));
367                        if (dai != null) {
368                            ActiveAdmin ap = new ActiveAdmin(dai);
369                            ap.readFromXml(parser);
370                            mAdminMap.put(ap.info.getComponent(), ap);
371                            mAdminList.add(ap);
372                        }
373                    } catch (RuntimeException e) {
374                        Log.w(TAG, "Failed loading admin " + name, e);
375                    }
376                } else if ("failed-password-attempts".equals(tag)) {
377                    mFailedPasswordAttempts = Integer.parseInt(
378                            parser.getAttributeValue(null, "value"));
379                    XmlUtils.skipCurrentTag(parser);
380                } else {
381                    Log.w(TAG, "Unknown tag: " + tag);
382                    XmlUtils.skipCurrentTag(parser);
383                }
384            }
385        } catch (NullPointerException e) {
386            Log.w(TAG, "failed parsing " + file + " " + e);
387        } catch (NumberFormatException e) {
388            Log.w(TAG, "failed parsing " + file + " " + e);
389        } catch (XmlPullParserException e) {
390            Log.w(TAG, "failed parsing " + file + " " + e);
391        } catch (IOException e) {
392            Log.w(TAG, "failed parsing " + file + " " + e);
393        } catch (IndexOutOfBoundsException e) {
394            Log.w(TAG, "failed parsing " + file + " " + e);
395        }
396        try {
397            if (stream != null) {
398                stream.close();
399            }
400        } catch (IOException e) {
401            // Ignore
402        }
403
404        long timeMs = getMaximumTimeToLock(null);
405        if (timeMs <= 0) {
406            timeMs = Integer.MAX_VALUE;
407        }
408        try {
409            getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
410        } catch (RemoteException e) {
411            Log.w(TAG, "Failure talking with power manager", e);
412        }
413    }
414
415    public void systemReady() {
416        synchronized (this) {
417            loadSettingsLocked();
418        }
419    }
420
421    public void setActiveAdmin(ComponentName adminReceiver) {
422        mContext.enforceCallingOrSelfPermission(
423                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
424
425        DeviceAdminInfo info = findAdmin(adminReceiver);
426        if (info == null) {
427            throw new IllegalArgumentException("Bad admin: " + adminReceiver);
428        }
429        synchronized (this) {
430            long ident = Binder.clearCallingIdentity();
431            try {
432                if (getActiveAdminUncheckedLocked(adminReceiver) != null) {
433                    throw new IllegalArgumentException("Admin is already added");
434                }
435                ActiveAdmin admin = new ActiveAdmin(info);
436                mAdminMap.put(adminReceiver, admin);
437                mAdminList.add(admin);
438                saveSettingsLocked();
439                sendAdminCommandLocked(admin,
440                        DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED);
441            } finally {
442                Binder.restoreCallingIdentity(ident);
443            }
444        }
445    }
446
447    public boolean isAdminActive(ComponentName adminReceiver) {
448        synchronized (this) {
449            return getActiveAdminUncheckedLocked(adminReceiver) != null;
450        }
451    }
452
453    public List<ComponentName> getActiveAdmins() {
454        synchronized (this) {
455            final int N = mAdminList.size();
456            if (N <= 0) {
457                return null;
458            }
459            ArrayList<ComponentName> res = new ArrayList<ComponentName>(N);
460            for (int i=0; i<N; i++) {
461                res.add(mAdminList.get(i).info.getComponent());
462            }
463            return res;
464        }
465    }
466
467    public boolean packageHasActiveAdmins(String packageName) {
468        synchronized (this) {
469            final int N = mAdminList.size();
470            for (int i=0; i<N; i++) {
471                if (mAdminList.get(i).info.getPackageName().equals(packageName)) {
472                    return true;
473                }
474            }
475            return false;
476        }
477    }
478
479    public void removeActiveAdmin(ComponentName adminReceiver) {
480        synchronized (this) {
481            ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
482            if (admin == null) {
483                return;
484            }
485            if (admin.getUid() != Binder.getCallingUid()) {
486                mContext.enforceCallingOrSelfPermission(
487                        android.Manifest.permission.BIND_DEVICE_ADMIN, null);
488            }
489            long ident = Binder.clearCallingIdentity();
490            try {
491                removeActiveAdminLocked(adminReceiver);
492            } finally {
493                Binder.restoreCallingIdentity(ident);
494            }
495        }
496    }
497
498    public void setPasswordQuality(ComponentName who, int mode) {
499        synchronized (this) {
500            if (who == null) {
501                throw new NullPointerException("ComponentName is null");
502            }
503            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
504                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
505            if (ap.passwordQuality != mode) {
506                ap.passwordQuality = mode;
507                saveSettingsLocked();
508            }
509        }
510    }
511
512    public int getPasswordQuality(ComponentName who) {
513        synchronized (this) {
514            int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
515
516            if (who != null) {
517                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
518                return admin != null ? admin.passwordQuality : mode;
519            }
520
521            final int N = mAdminList.size();
522            for  (int i=0; i<N; i++) {
523                ActiveAdmin admin = mAdminList.get(i);
524                if (mode < admin.passwordQuality) {
525                    mode = admin.passwordQuality;
526                }
527            }
528            return mode;
529        }
530    }
531
532    public void setPasswordMinimumLength(ComponentName who, int length) {
533        synchronized (this) {
534            if (who == null) {
535                throw new NullPointerException("ComponentName is null");
536            }
537            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
538                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
539            if (ap.minimumPasswordLength != length) {
540                ap.minimumPasswordLength = length;
541                saveSettingsLocked();
542            }
543        }
544    }
545
546    public int getPasswordMinimumLength(ComponentName who) {
547        synchronized (this) {
548            int length = 0;
549
550            if (who != null) {
551                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
552                return admin != null ? admin.minimumPasswordLength : length;
553            }
554
555            final int N = mAdminList.size();
556            for  (int i=0; i<N; i++) {
557                ActiveAdmin admin = mAdminList.get(i);
558                if (length < admin.minimumPasswordLength) {
559                    length = admin.minimumPasswordLength;
560                }
561            }
562            return length;
563        }
564    }
565
566    public boolean isActivePasswordSufficient() {
567        synchronized (this) {
568            // This API can only be called by an active device admin,
569            // so try to retrieve it to check that the caller is one.
570            getActiveAdminForCallerLocked(null,
571                    DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
572            return mActivePasswordQuality >= getPasswordQuality(null)
573                    && mActivePasswordLength >= getPasswordMinimumLength(null);
574        }
575    }
576
577    public int getCurrentFailedPasswordAttempts() {
578        synchronized (this) {
579            // This API can only be called by an active device admin,
580            // so try to retrieve it to check that the caller is one.
581            getActiveAdminForCallerLocked(null,
582                    DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
583            return mFailedPasswordAttempts;
584        }
585    }
586
587    public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) {
588        synchronized (this) {
589            // This API can only be called by an active device admin,
590            // so try to retrieve it to check that the caller is one.
591            getActiveAdminForCallerLocked(who,
592                    DeviceAdminInfo.USES_POLICY_WIPE_DATA);
593            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
594                    DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
595            if (ap.maximumFailedPasswordsForWipe != num) {
596                ap.maximumFailedPasswordsForWipe = num;
597                saveSettingsLocked();
598            }
599        }
600    }
601
602    public int getMaximumFailedPasswordsForWipe(ComponentName who) {
603        synchronized (this) {
604            int count = 0;
605
606            if (who != null) {
607                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
608                return admin != null ? admin.maximumFailedPasswordsForWipe : count;
609            }
610
611            final int N = mAdminList.size();
612            for  (int i=0; i<N; i++) {
613                ActiveAdmin admin = mAdminList.get(i);
614                if (count == 0) {
615                    count = admin.maximumFailedPasswordsForWipe;
616                } else if (admin.maximumFailedPasswordsForWipe != 0
617                        && count > admin.maximumFailedPasswordsForWipe) {
618                    count = admin.maximumFailedPasswordsForWipe;
619                }
620            }
621            return count;
622        }
623    }
624
625    public boolean resetPassword(String password) {
626        int quality;
627        synchronized (this) {
628            // This API can only be called by an active device admin,
629            // so try to retrieve it to check that the caller is one.
630            getActiveAdminForCallerLocked(null,
631                    DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
632            quality = getPasswordQuality(null);
633            if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
634                int adjQuality = LockPatternUtils.adjustPasswordMode(password, quality);
635                if (adjQuality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
636                    Log.w(TAG, "resetPassword: password does not meet quality " + quality);
637                    return false;
638                }
639                quality = adjQuality;
640            }
641            int length = getPasswordMinimumLength(null);
642            if (password.length() < length) {
643                Log.w(TAG, "resetPassword: password does not meet length " + length);
644                return false;
645            }
646        }
647
648        // Don't do this with the lock held, because it is going to call
649        // back in to the service.
650        long ident = Binder.clearCallingIdentity();
651        try {
652            LockPatternUtils utils = new LockPatternUtils(mContext);
653            utils.saveLockPassword(password, quality);
654        } finally {
655            Binder.restoreCallingIdentity(ident);
656        }
657
658        return true;
659    }
660
661    public void setMaximumTimeToLock(ComponentName who, long timeMs) {
662        synchronized (this) {
663            if (who == null) {
664                throw new NullPointerException("ComponentName is null");
665            }
666            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
667                    DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
668            if (ap.maximumTimeToUnlock != timeMs) {
669                ap.maximumTimeToUnlock = timeMs;
670
671                long ident = Binder.clearCallingIdentity();
672                try {
673                    saveSettingsLocked();
674
675                    timeMs = getMaximumTimeToLock(null);
676                    if (timeMs <= 0) {
677                        timeMs = Integer.MAX_VALUE;
678                    }
679
680                    try {
681                        getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
682                    } catch (RemoteException e) {
683                        Log.w(TAG, "Failure talking with power manager", e);
684                    }
685                } finally {
686                    Binder.restoreCallingIdentity(ident);
687                }
688            }
689        }
690    }
691
692    public long getMaximumTimeToLock(ComponentName who) {
693        synchronized (this) {
694            long time = 0;
695
696            if (who != null) {
697                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
698                return admin != null ? admin.maximumTimeToUnlock : time;
699            }
700
701            final int N = mAdminList.size();
702            for  (int i=0; i<N; i++) {
703                ActiveAdmin admin = mAdminList.get(i);
704                if (time == 0) {
705                    time = admin.maximumTimeToUnlock;
706                } else if (admin.maximumTimeToUnlock != 0
707                        && time > admin.maximumTimeToUnlock) {
708                    time = admin.maximumTimeToUnlock;
709                }
710            }
711            return time;
712        }
713    }
714
715    public void lockNow() {
716        synchronized (this) {
717            // This API can only be called by an active device admin,
718            // so try to retrieve it to check that the caller is one.
719            getActiveAdminForCallerLocked(null,
720                    DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
721            long ident = Binder.clearCallingIdentity();
722            try {
723                mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(),
724                        WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN);
725            } catch (RemoteException e) {
726            } finally {
727                Binder.restoreCallingIdentity(ident);
728            }
729        }
730    }
731
732    void wipeDataLocked(int flags) {
733        try {
734            RecoverySystem.rebootWipeUserData(mContext);
735        } catch (IOException e) {
736            Log.w(TAG, "Failed requesting data wipe", e);
737        }
738    }
739
740    public void wipeData(int flags) {
741        synchronized (this) {
742            // This API can only be called by an active device admin,
743            // so try to retrieve it to check that the caller is one.
744            getActiveAdminForCallerLocked(null,
745                    DeviceAdminInfo.USES_POLICY_WIPE_DATA);
746            long ident = Binder.clearCallingIdentity();
747            try {
748                wipeDataLocked(flags);
749            } finally {
750                Binder.restoreCallingIdentity(ident);
751            }
752        }
753    }
754
755    public void getRemoveWarning(ComponentName comp, final RemoteCallback result) {
756        mContext.enforceCallingOrSelfPermission(
757                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
758
759        synchronized (this) {
760            ActiveAdmin admin = getActiveAdminUncheckedLocked(comp);
761            if (admin == null) {
762                try {
763                    result.sendResult(null);
764                } catch (RemoteException e) {
765                }
766                return;
767            }
768            Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
769            intent.setComponent(admin.info.getComponent());
770            mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
771                @Override
772                public void onReceive(Context context, Intent intent) {
773                    try {
774                        result.sendResult(getResultExtras(false));
775                    } catch (RemoteException e) {
776                    }
777                }
778            }, null, Activity.RESULT_OK, null, null);
779        }
780    }
781
782    public void setActivePasswordState(int quality, int length) {
783        mContext.enforceCallingOrSelfPermission(
784                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
785
786        synchronized (this) {
787            if (mActivePasswordQuality != quality || mActivePasswordLength != length
788                    || mFailedPasswordAttempts != 0) {
789                long ident = Binder.clearCallingIdentity();
790                try {
791                    mActivePasswordQuality = quality;
792                    mActivePasswordLength = length;
793                    if (mFailedPasswordAttempts != 0) {
794                        mFailedPasswordAttempts = 0;
795                        saveSettingsLocked();
796                    }
797                    sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
798                            DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
799                } finally {
800                    Binder.restoreCallingIdentity(ident);
801                }
802            }
803        }
804    }
805
806    public void reportFailedPasswordAttempt() {
807        mContext.enforceCallingOrSelfPermission(
808                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
809
810        synchronized (this) {
811            long ident = Binder.clearCallingIdentity();
812            try {
813                mFailedPasswordAttempts++;
814                saveSettingsLocked();
815                int max = getMaximumFailedPasswordsForWipe(null);
816                if (max > 0 && mFailedPasswordAttempts >= max) {
817                    wipeDataLocked(0);
818                }
819                sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
820                        DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
821            } finally {
822                Binder.restoreCallingIdentity(ident);
823            }
824        }
825    }
826
827    public void reportSuccessfulPasswordAttempt() {
828        mContext.enforceCallingOrSelfPermission(
829                android.Manifest.permission.BIND_DEVICE_ADMIN, null);
830
831        synchronized (this) {
832            if (mFailedPasswordAttempts != 0) {
833                long ident = Binder.clearCallingIdentity();
834                try {
835                    mFailedPasswordAttempts = 0;
836                    saveSettingsLocked();
837                    sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
838                            DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
839                } finally {
840                    Binder.restoreCallingIdentity(ident);
841                }
842            }
843        }
844    }
845}
846