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