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 android.app.admin;
18
19import org.xmlpull.v1.XmlPullParserException;
20
21import android.annotation.SdkConstant;
22import android.annotation.SdkConstant.SdkConstantType;
23import android.content.ComponentName;
24import android.content.Context;
25import android.content.pm.ActivityInfo;
26import android.content.pm.PackageManager;
27import android.content.pm.ResolveInfo;
28import android.os.Handler;
29import android.os.RemoteCallback;
30import android.os.RemoteException;
31import android.os.ServiceManager;
32import android.util.Log;
33
34import java.io.IOException;
35import java.util.List;
36
37/**
38 * Public interface for managing policies enforced on a device.  Most clients
39 * of this class must have published a {@link DeviceAdminReceiver} that the user
40 * has currently enabled.
41 */
42public class DevicePolicyManager {
43    private static String TAG = "DevicePolicyManager";
44    private static boolean DEBUG = false;
45    private static boolean localLOGV = DEBUG || android.util.Config.LOGV;
46
47    private final Context mContext;
48    private final IDevicePolicyManager mService;
49
50    private final Handler mHandler;
51
52    private DevicePolicyManager(Context context, Handler handler) {
53        mContext = context;
54        mHandler = handler;
55        mService = IDevicePolicyManager.Stub.asInterface(
56                ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
57    }
58
59    /** @hide */
60    public static DevicePolicyManager create(Context context, Handler handler) {
61        DevicePolicyManager me = new DevicePolicyManager(context, handler);
62        return me.mService != null ? me : null;
63    }
64
65    /**
66     * Activity action: ask the user to add a new device administrator to the system.
67     * The desired policy is the ComponentName of the policy in the
68     * {@link #EXTRA_DEVICE_ADMIN} extra field.  This will invoke a UI to
69     * bring the user through adding the device administrator to the system (or
70     * allowing them to reject it).
71     *
72     * <p>You can optionally include the {@link #EXTRA_ADD_EXPLANATION}
73     * field to provide the user with additional explanation (in addition
74     * to your component's description) about what is being added.
75     */
76    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
77    public static final String ACTION_ADD_DEVICE_ADMIN
78            = "android.app.action.ADD_DEVICE_ADMIN";
79
80    /**
81     * Activity action: send when any policy admin changes a policy.
82     * This is generally used to find out when a new policy is in effect.
83     *
84     * @hide
85     */
86    public static final String ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED
87            = "android.app.action.DEVICE_POLICY_MANAGER_STATE_CHANGED";
88
89    /**
90     * The ComponentName of the administrator component.
91     *
92     * @see #ACTION_ADD_DEVICE_ADMIN
93     */
94    public static final String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
95
96    /**
97     * An optional CharSequence providing additional explanation for why the
98     * admin is being added.
99     *
100     * @see #ACTION_ADD_DEVICE_ADMIN
101     */
102    public static final String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
103
104    /**
105     * Activity action: have the user enter a new password.  This activity
106     * should be launched after using {@link #setPasswordQuality(ComponentName, int)}
107     * or {@link #setPasswordMinimumLength(ComponentName, int)} to have the
108     * user enter a new password that meets the current requirements.  You can
109     * use {@link #isActivePasswordSufficient()} to determine whether you need
110     * to have the user select a new password in order to meet the current
111     * constraints.  Upon being resumed from this activity,
112     * you can check the new password characteristics to see if they are
113     * sufficient.
114     */
115    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
116    public static final String ACTION_SET_NEW_PASSWORD
117            = "android.app.action.SET_NEW_PASSWORD";
118
119    /**
120     * Return true if the given administrator component is currently
121     * active (enabled) in the system.
122     */
123    public boolean isAdminActive(ComponentName who) {
124        if (mService != null) {
125            try {
126                return mService.isAdminActive(who);
127            } catch (RemoteException e) {
128                Log.w(TAG, "Failed talking with device policy service", e);
129            }
130        }
131        return false;
132    }
133
134    /**
135     * Return a list of all currently active device administrator's component
136     * names.  Note that if there are no administrators than null may be
137     * returned.
138     */
139    public List<ComponentName> getActiveAdmins() {
140        if (mService != null) {
141            try {
142                return mService.getActiveAdmins();
143            } catch (RemoteException e) {
144                Log.w(TAG, "Failed talking with device policy service", e);
145            }
146        }
147        return null;
148    }
149
150    /**
151     * @hide
152     */
153    public boolean packageHasActiveAdmins(String packageName) {
154        if (mService != null) {
155            try {
156                return mService.packageHasActiveAdmins(packageName);
157            } catch (RemoteException e) {
158                Log.w(TAG, "Failed talking with device policy service", e);
159            }
160        }
161        return false;
162    }
163
164    /**
165     * Remove a current administration component.  This can only be called
166     * by the application that owns the administration component; if you
167     * try to remove someone else's component, a security exception will be
168     * thrown.
169     */
170    public void removeActiveAdmin(ComponentName who) {
171        if (mService != null) {
172            try {
173                mService.removeActiveAdmin(who);
174            } catch (RemoteException e) {
175                Log.w(TAG, "Failed talking with device policy service", e);
176            }
177        }
178    }
179
180    /**
181     * Constant for {@link #setPasswordQuality}: the policy has no requirements
182     * for the password.  Note that quality constants are ordered so that higher
183     * values are more restrictive.
184     */
185    public static final int PASSWORD_QUALITY_UNSPECIFIED = 0;
186
187    /**
188     * Constant for {@link #setPasswordQuality}: the policy requires some kind
189     * of password, but doesn't care what it is.  Note that quality constants
190     * are ordered so that higher values are more restrictive.
191     */
192    public static final int PASSWORD_QUALITY_SOMETHING = 0x10000;
193
194    /**
195     * Constant for {@link #setPasswordQuality}: the user must have entered a
196     * password containing at least numeric characters.  Note that quality
197     * constants are ordered so that higher values are more restrictive.
198     */
199    public static final int PASSWORD_QUALITY_NUMERIC = 0x20000;
200
201    /**
202     * Constant for {@link #setPasswordQuality}: the user must have entered a
203     * password containing at least alphabetic (or other symbol) characters.
204     * Note that quality constants are ordered so that higher values are more
205     * restrictive.
206     */
207    public static final int PASSWORD_QUALITY_ALPHABETIC = 0x40000;
208
209    /**
210     * Constant for {@link #setPasswordQuality}: the user must have entered a
211     * password containing at least <em>both></em> numeric <em>and</em>
212     * alphabetic (or other symbol) characters.  Note that quality constants are
213     * ordered so that higher values are more restrictive.
214     */
215    public static final int PASSWORD_QUALITY_ALPHANUMERIC = 0x50000;
216
217    /**
218     * Called by an application that is administering the device to set the
219     * password restrictions it is imposing.  After setting this, the user
220     * will not be able to enter a new password that is not at least as
221     * restrictive as what has been set.  Note that the current password
222     * will remain until the user has set a new one, so the change does not
223     * take place immediately.  To prompt the user for a new password, use
224     * {@link #ACTION_SET_NEW_PASSWORD} after setting this value.
225     *
226     * <p>Quality constants are ordered so that higher values are more restrictive;
227     * thus the highest requested quality constant (between the policy set here,
228     * the user's preference, and any other considerations) is the one that
229     * is in effect.
230     *
231     * <p>The calling device admin must have requested
232     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
233     * this method; if it has not, a security exception will be thrown.
234     *
235     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
236     * @param quality The new desired quality.  One of
237     * {@link #PASSWORD_QUALITY_UNSPECIFIED}, {@link #PASSWORD_QUALITY_SOMETHING},
238     * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_ALPHABETIC},
239     * or {@link #PASSWORD_QUALITY_ALPHANUMERIC}.
240     */
241    public void setPasswordQuality(ComponentName admin, int quality) {
242        if (mService != null) {
243            try {
244                mService.setPasswordQuality(admin, quality);
245            } catch (RemoteException e) {
246                Log.w(TAG, "Failed talking with device policy service", e);
247            }
248        }
249    }
250
251    /**
252     * Retrieve the current minimum password quality for all admins
253     * or a particular one.
254     * @param admin The name of the admin component to check, or null to aggregate
255     * all admins.
256     */
257    public int getPasswordQuality(ComponentName admin) {
258        if (mService != null) {
259            try {
260                return mService.getPasswordQuality(admin);
261            } catch (RemoteException e) {
262                Log.w(TAG, "Failed talking with device policy service", e);
263            }
264        }
265        return PASSWORD_QUALITY_UNSPECIFIED;
266    }
267
268    /**
269     * Called by an application that is administering the device to set the
270     * minimum allowed password length.  After setting this, the user
271     * will not be able to enter a new password that is not at least as
272     * restrictive as what has been set.  Note that the current password
273     * will remain until the user has set a new one, so the change does not
274     * take place immediately.  To prompt the user for a new password, use
275     * {@link #ACTION_SET_NEW_PASSWORD} after setting this value.  This
276     * constraint is only imposed if the administrator has also requested either
277     * {@link #PASSWORD_QUALITY_NUMERIC}, {@link #PASSWORD_QUALITY_ALPHABETIC},
278     * or {@link #PASSWORD_QUALITY_ALPHANUMERIC}
279     * with {@link #setPasswordQuality}.
280     *
281     * <p>The calling device admin must have requested
282     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
283     * this method; if it has not, a security exception will be thrown.
284     *
285     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
286     * @param length The new desired minimum password length.  A value of 0
287     * means there is no restriction.
288     */
289    public void setPasswordMinimumLength(ComponentName admin, int length) {
290        if (mService != null) {
291            try {
292                mService.setPasswordMinimumLength(admin, length);
293            } catch (RemoteException e) {
294                Log.w(TAG, "Failed talking with device policy service", e);
295            }
296        }
297    }
298
299    /**
300     * Retrieve the current minimum password length for all admins
301     * or a particular one.
302     * @param admin The name of the admin component to check, or null to aggregate
303     * all admins.
304     */
305    public int getPasswordMinimumLength(ComponentName admin) {
306        if (mService != null) {
307            try {
308                return mService.getPasswordMinimumLength(admin);
309            } catch (RemoteException e) {
310                Log.w(TAG, "Failed talking with device policy service", e);
311            }
312        }
313        return 0;
314    }
315
316    /**
317     * Return the maximum password length that the device supports for a
318     * particular password quality.
319     * @param quality The quality being interrogated.
320     * @return Returns the maximum length that the user can enter.
321     */
322    public int getPasswordMaximumLength(int quality) {
323        // Kind-of arbitrary.
324        return 16;
325    }
326
327    /**
328     * Determine whether the current password the user has set is sufficient
329     * to meet the policy requirements (quality, minimum length) that have been
330     * requested.
331     *
332     * <p>The calling device admin must have requested
333     * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call
334     * this method; if it has not, a security exception will be thrown.
335     *
336     * @return Returns true if the password meets the current requirements,
337     * else false.
338     */
339    public boolean isActivePasswordSufficient() {
340        if (mService != null) {
341            try {
342                return mService.isActivePasswordSufficient();
343            } catch (RemoteException e) {
344                Log.w(TAG, "Failed talking with device policy service", e);
345            }
346        }
347        return false;
348    }
349
350    /**
351     * Retrieve the number of times the user has failed at entering a
352     * password since that last successful password entry.
353     *
354     * <p>The calling device admin must have requested
355     * {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} to be able to call
356     * this method; if it has not, a security exception will be thrown.
357     */
358    public int getCurrentFailedPasswordAttempts() {
359        if (mService != null) {
360            try {
361                return mService.getCurrentFailedPasswordAttempts();
362            } catch (RemoteException e) {
363                Log.w(TAG, "Failed talking with device policy service", e);
364            }
365        }
366        return -1;
367    }
368
369    /**
370     * Setting this to a value greater than zero enables a built-in policy
371     * that will perform a device wipe after too many incorrect
372     * device-unlock passwords have been entered.  This built-in policy combines
373     * watching for failed passwords and wiping the device, and requires
374     * that you request both {@link DeviceAdminInfo#USES_POLICY_WATCH_LOGIN} and
375     * {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA}}.
376     *
377     * <p>To implement any other policy (e.g. wiping data for a particular
378     * application only, erasing or revoking credentials, or reporting the
379     * failure to a server), you should implement
380     * {@link DeviceAdminReceiver#onPasswordFailed(Context, android.content.Intent)}
381     * instead.  Do not use this API, because if the maximum count is reached,
382     * the device will be wiped immediately, and your callback will not be invoked.
383     *
384     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
385     * @param num The number of failed password attempts at which point the
386     * device will wipe its data.
387     */
388    public void setMaximumFailedPasswordsForWipe(ComponentName admin, int num) {
389        if (mService != null) {
390            try {
391                mService.setMaximumFailedPasswordsForWipe(admin, num);
392            } catch (RemoteException e) {
393                Log.w(TAG, "Failed talking with device policy service", e);
394            }
395        }
396    }
397
398    /**
399     * Retrieve the current maximum number of login attempts that are allowed
400     * before the device wipes itself, for all admins
401     * or a particular one.
402     * @param admin The name of the admin component to check, or null to aggregate
403     * all admins.
404     */
405    public int getMaximumFailedPasswordsForWipe(ComponentName admin) {
406        if (mService != null) {
407            try {
408                return mService.getMaximumFailedPasswordsForWipe(admin);
409            } catch (RemoteException e) {
410                Log.w(TAG, "Failed talking with device policy service", e);
411            }
412        }
413        return 0;
414    }
415
416    /**
417     * Flag for {@link #resetPassword}: don't allow other admins to change
418     * the password again until the user has entered it.
419     */
420    public static final int RESET_PASSWORD_REQUIRE_ENTRY = 0x0001;
421
422    /**
423     * Force a new device unlock password (the password needed to access the
424     * entire device, not for individual accounts) on the user.  This takes
425     * effect immediately.
426     * The given password must be sufficient for the
427     * current password quality and length constraints as returned by
428     * {@link #getPasswordQuality(ComponentName)} and
429     * {@link #getPasswordMinimumLength(ComponentName)}; if it does not meet
430     * these constraints, then it will be rejected and false returned.  Note
431     * that the password may be a stronger quality (containing alphanumeric
432     * characters when the requested quality is only numeric), in which case
433     * the currently active quality will be increased to match.
434     *
435     * <p>The calling device admin must have requested
436     * {@link DeviceAdminInfo#USES_POLICY_RESET_PASSWORD} to be able to call
437     * this method; if it has not, a security exception will be thrown.
438     *
439     * @param password The new password for the user.
440     * @param flags May be 0 or {@link #RESET_PASSWORD_REQUIRE_ENTRY}.
441     * @return Returns true if the password was applied, or false if it is
442     * not acceptable for the current constraints.
443     */
444    public boolean resetPassword(String password, int flags) {
445        if (mService != null) {
446            try {
447                return mService.resetPassword(password, flags);
448            } catch (RemoteException e) {
449                Log.w(TAG, "Failed talking with device policy service", e);
450            }
451        }
452        return false;
453    }
454
455    /**
456     * Called by an application that is administering the device to set the
457     * maximum time for user activity until the device will lock.  This limits
458     * the length that the user can set.  It takes effect immediately.
459     *
460     * <p>The calling device admin must have requested
461     * {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} to be able to call
462     * this method; if it has not, a security exception will be thrown.
463     *
464     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
465     * @param timeMs The new desired maximum time to lock in milliseconds.
466     * A value of 0 means there is no restriction.
467     */
468    public void setMaximumTimeToLock(ComponentName admin, long timeMs) {
469        if (mService != null) {
470            try {
471                mService.setMaximumTimeToLock(admin, timeMs);
472            } catch (RemoteException e) {
473                Log.w(TAG, "Failed talking with device policy service", e);
474            }
475        }
476    }
477
478    /**
479     * Retrieve the current maximum time to unlock for all admins
480     * or a particular one.
481     * @param admin The name of the admin component to check, or null to aggregate
482     * all admins.
483     */
484    public long getMaximumTimeToLock(ComponentName admin) {
485        if (mService != null) {
486            try {
487                return mService.getMaximumTimeToLock(admin);
488            } catch (RemoteException e) {
489                Log.w(TAG, "Failed talking with device policy service", e);
490            }
491        }
492        return 0;
493    }
494
495    /**
496     * Make the device lock immediately, as if the lock screen timeout has
497     * expired at the point of this call.
498     *
499     * <p>The calling device admin must have requested
500     * {@link DeviceAdminInfo#USES_POLICY_FORCE_LOCK} to be able to call
501     * this method; if it has not, a security exception will be thrown.
502     */
503    public void lockNow() {
504        if (mService != null) {
505            try {
506                mService.lockNow();
507            } catch (RemoteException e) {
508                Log.w(TAG, "Failed talking with device policy service", e);
509            }
510        }
511    }
512
513    /**
514     * Flag for {@link #wipeData(int)}: also erase the device's external
515     * storage.
516     */
517    public static final int WIPE_EXTERNAL_STORAGE = 0x0001;
518
519    /**
520     * Ask the user date be wiped.  This will cause the device to reboot,
521     * erasing all user data while next booting up.  External storage such
522     * as SD cards will not be erased.
523     *
524     * <p>The calling device admin must have requested
525     * {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} to be able to call
526     * this method; if it has not, a security exception will be thrown.
527     *
528     * @param flags Bit mask of additional options: currently must be 0.
529     */
530    public void wipeData(int flags) {
531        if (mService != null) {
532            try {
533                mService.wipeData(flags);
534            } catch (RemoteException e) {
535                Log.w(TAG, "Failed talking with device policy service", e);
536            }
537        }
538    }
539
540    /**
541     * @hide
542     */
543    public void setActiveAdmin(ComponentName policyReceiver) {
544        if (mService != null) {
545            try {
546                mService.setActiveAdmin(policyReceiver);
547            } catch (RemoteException e) {
548                Log.w(TAG, "Failed talking with device policy service", e);
549            }
550        }
551    }
552
553    /**
554     * @hide
555     */
556    public DeviceAdminInfo getAdminInfo(ComponentName cn) {
557        ActivityInfo ai;
558        try {
559            ai = mContext.getPackageManager().getReceiverInfo(cn,
560                    PackageManager.GET_META_DATA);
561        } catch (PackageManager.NameNotFoundException e) {
562            Log.w(TAG, "Unable to retrieve device policy " + cn, e);
563            return null;
564        }
565
566        ResolveInfo ri = new ResolveInfo();
567        ri.activityInfo = ai;
568
569        try {
570            return new DeviceAdminInfo(mContext, ri);
571        } catch (XmlPullParserException e) {
572            Log.w(TAG, "Unable to parse device policy " + cn, e);
573            return null;
574        } catch (IOException e) {
575            Log.w(TAG, "Unable to parse device policy " + cn, e);
576            return null;
577        }
578    }
579
580    /**
581     * @hide
582     */
583    public void getRemoveWarning(ComponentName admin, RemoteCallback result) {
584        if (mService != null) {
585            try {
586                mService.getRemoveWarning(admin, result);
587            } catch (RemoteException e) {
588                Log.w(TAG, "Failed talking with device policy service", e);
589            }
590        }
591    }
592
593    /**
594     * @hide
595     */
596    public void setActivePasswordState(int quality, int length) {
597        if (mService != null) {
598            try {
599                mService.setActivePasswordState(quality, length);
600            } catch (RemoteException e) {
601                Log.w(TAG, "Failed talking with device policy service", e);
602            }
603        }
604    }
605
606    /**
607     * @hide
608     */
609    public void reportFailedPasswordAttempt() {
610        if (mService != null) {
611            try {
612                mService.reportFailedPasswordAttempt();
613            } catch (RemoteException e) {
614                Log.w(TAG, "Failed talking with device policy service", e);
615            }
616        }
617    }
618
619    /**
620     * @hide
621     */
622    public void reportSuccessfulPasswordAttempt() {
623        if (mService != null) {
624            try {
625                mService.reportSuccessfulPasswordAttempt();
626            } catch (RemoteException e) {
627                Log.w(TAG, "Failed talking with device policy service", e);
628            }
629        }
630    }
631}
632