blob: ebd6f3d0bac37641faacd547aac6e990c3706212 [file] [log] [blame]
Dianne Hackbornd6847842010-01-12 18:14:19 -08001/*
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;
Dianne Hackborndf83afa2010-01-20 13:37:26 -080020import com.android.internal.widget.LockPatternUtils;
Dianne Hackbornd6847842010-01-12 18:14:19 -080021
22import org.xmlpull.v1.XmlPullParser;
23import org.xmlpull.v1.XmlPullParserException;
24import org.xmlpull.v1.XmlSerializer;
25
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080026import android.app.Activity;
Dianne Hackbornd6847842010-01-12 18:14:19 -080027import android.app.DeviceAdmin;
28import android.app.DeviceAdminInfo;
29import android.app.DevicePolicyManager;
30import android.app.IDevicePolicyManager;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080031import android.content.BroadcastReceiver;
Dianne Hackbornd6847842010-01-12 18:14:19 -080032import 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;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080038import android.os.Handler;
Dianne Hackborndf83afa2010-01-20 13:37:26 -080039import android.os.IBinder;
40import android.os.IPowerManager;
Dianne Hackborndf83afa2010-01-20 13:37:26 -080041import android.os.RecoverySystem;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080042import android.os.RemoteCallback;
Dianne Hackborndf83afa2010-01-20 13:37:26 -080043import android.os.RemoteException;
44import android.os.ServiceManager;
Dianne Hackbornd6847842010-01-12 18:14:19 -080045import android.util.Log;
46import android.util.Xml;
47
48import java.io.File;
49import java.io.FileInputStream;
50import java.io.FileOutputStream;
51import java.io.IOException;
52import java.util.List;
53
54/**
55 * Implementation of the device policy APIs.
56 */
57public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
58 private static final String TAG = "DevicePolicyManagerService";
59
60 private final Context mContext;
61
Dianne Hackborndf83afa2010-01-20 13:37:26 -080062 IPowerManager mIPowerManager;
63
Dianne Hackbornd6847842010-01-12 18:14:19 -080064 int mActivePasswordMode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
65 int mActivePasswordLength = 0;
66 int mFailedPasswordAttempts = 0;
67
68 ActiveAdmin mActiveAdmin;
69
70 static class ActiveAdmin {
Dianne Hackbornd6847842010-01-12 18:14:19 -080071 final DeviceAdminInfo info;
Dianne Hackbornd6847842010-01-12 18:14:19 -080072
73 int passwordMode = DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
74 int minimumPasswordLength = 0;
75 long maximumTimeToUnlock = 0;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080076 int maximumFailedPasswordsForWipe = 0;
77
78 ActiveAdmin(DeviceAdminInfo _info) {
79 info = _info;
80 }
81
82 int getUid() { return info.getActivityInfo().applicationInfo.uid; }
83
84 void writeToXml(XmlSerializer out)
85 throws IllegalArgumentException, IllegalStateException, IOException {
86 if (passwordMode != DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED) {
87 out.startTag(null, "password-mode");
88 out.attribute(null, "value", Integer.toString(passwordMode));
89 out.endTag(null, "password-mode");
90 if (minimumPasswordLength > 0) {
91 out.startTag(null, "min-password-length");
92 out.attribute(null, "value", Integer.toString(minimumPasswordLength));
93 out.endTag(null, "mn-password-length");
94 }
95 }
96 if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED) {
97 out.startTag(null, "max-time-to-unlock");
98 out.attribute(null, "value", Long.toString(maximumTimeToUnlock));
99 out.endTag(null, "max-time-to-unlock");
100 }
101 if (maximumFailedPasswordsForWipe != 0) {
102 out.startTag(null, "max-failed-password-wipe");
103 out.attribute(null, "value", Integer.toString(maximumFailedPasswordsForWipe));
104 out.endTag(null, "max-failed-password-wipe");
105 }
106 }
107
108 void readFromXml(XmlPullParser parser)
109 throws XmlPullParserException, IOException {
110 int outerDepth = parser.getDepth();
111 int type;
112 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
113 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
114 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
115 continue;
116 }
117 String tag = parser.getName();
118 if ("password-mode".equals(tag)) {
119 passwordMode = Integer.parseInt(
120 parser.getAttributeValue(null, "value"));
121 } else if ("min-password-length".equals(tag)) {
122 minimumPasswordLength = Integer.parseInt(
123 parser.getAttributeValue(null, "value"));
124 } else if ("max-time-to-unlock".equals(tag)) {
125 maximumTimeToUnlock = Long.parseLong(
126 parser.getAttributeValue(null, "value"));
127 } else if ("max-failed-password-wipe".equals(tag)) {
128 maximumFailedPasswordsForWipe = Integer.parseInt(
129 parser.getAttributeValue(null, "value"));
130 }
131 }
132 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800133 }
134
135 /**
136 * Instantiates the service.
137 */
138 public DevicePolicyManagerService(Context context) {
139 mContext = context;
140 }
141
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800142 private IPowerManager getIPowerManager() {
143 if (mIPowerManager == null) {
144 IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
145 mIPowerManager = IPowerManager.Stub.asInterface(b);
146 }
147 return mIPowerManager;
148 }
149
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800150 ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) {
151 ActiveAdmin admin = mActiveAdmin;
152 if (admin != null
153 && who.getPackageName().equals(admin.info.getActivityInfo().packageName)
154 && who.getClassName().equals(admin.info.getActivityInfo().name)) {
155 return admin;
156 }
157 return null;
158 }
159
160 ActiveAdmin getActiveAdminForCallerLocked(ComponentName who)
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800161 throws SecurityException {
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800162 ActiveAdmin admin = mActiveAdmin;
163 if (admin != null && admin.getUid() == Binder.getCallingUid()) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800164 if (who != null) {
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800165 if (!who.getPackageName().equals(admin.info.getActivityInfo().packageName)
166 || !who.getClassName().equals(admin.info.getActivityInfo().name)) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800167 throw new SecurityException("Current admin is not " + who);
168 }
169 }
170 return mActiveAdmin;
171 }
172 throw new SecurityException("Current admin is not owned by uid " + Binder.getCallingUid());
173 }
174
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800175 ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
176 throws SecurityException {
177 ActiveAdmin admin = getActiveAdminForCallerLocked(who);
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 }
185
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800186 void sendAdminCommandLocked(ActiveAdmin admin, String action) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800187 Intent intent = new Intent(action);
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800188 intent.setComponent(admin.info.getComponent());
Dianne Hackbornd6847842010-01-12 18:14:19 -0800189 mContext.sendBroadcast(intent);
190 }
191
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800192 void sendAdminCommandLocked(String action, int reqPolicy) {
Dianne Hackborn4141d032010-01-21 16:29:00 -0800193 if (mActiveAdmin != null) {
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800194 if (mActiveAdmin.info.usesPolicy(reqPolicy)) {
195 return;
196 }
Dianne Hackborn4141d032010-01-21 16:29:00 -0800197 sendAdminCommandLocked(mActiveAdmin, action);
198 }
199 }
200
Dianne Hackbornd6847842010-01-12 18:14:19 -0800201 ComponentName getActiveAdminLocked() {
202 if (mActiveAdmin != null) {
203 return mActiveAdmin.info.getComponent();
204 }
205 return null;
206 }
207
208 void removeActiveAdminLocked(ComponentName adminReceiver) {
209 ComponentName cur = getActiveAdminLocked();
210 if (cur != null && cur.equals(adminReceiver)) {
211 sendAdminCommandLocked(mActiveAdmin,
212 DeviceAdmin.ACTION_DEVICE_ADMIN_DISABLED);
213 // XXX need to wait for it to complete.
214 mActiveAdmin = null;
215 }
216 }
217
218 public DeviceAdminInfo findAdmin(ComponentName adminName) {
219 Intent resolveIntent = new Intent();
220 resolveIntent.setComponent(adminName);
221 List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceivers(
222 resolveIntent, PackageManager.GET_META_DATA);
223 if (infos == null || infos.size() <= 0) {
224 throw new IllegalArgumentException("Unknown admin: " + adminName);
225 }
226
227 try {
228 return new DeviceAdminInfo(mContext, infos.get(0));
229 } catch (XmlPullParserException e) {
230 Log.w(TAG, "Bad device admin requested: " + adminName, e);
231 return null;
232 } catch (IOException e) {
233 Log.w(TAG, "Bad device admin requested: " + adminName, e);
234 return null;
235 }
236 }
237
238 private static JournaledFile makeJournaledFile() {
239 final String base = "/data/system/device_policies.xml";
240 return new JournaledFile(new File(base), new File(base + ".tmp"));
241 }
242
243 private void saveSettingsLocked() {
244 JournaledFile journal = makeJournaledFile();
245 FileOutputStream stream = null;
246 try {
247 stream = new FileOutputStream(journal.chooseForWrite(), false);
248 XmlSerializer out = new FastXmlSerializer();
249 out.setOutput(stream, "utf-8");
250 out.startDocument(null, true);
251
252 out.startTag(null, "policies");
253
254 ActiveAdmin ap = mActiveAdmin;
255 if (ap != null) {
256 out.startTag(null, "admin");
257 out.attribute(null, "name", ap.info.getComponent().flattenToString());
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800258 ap.writeToXml(out);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800259 out.endTag(null, "admin");
260 }
261 out.endTag(null, "policies");
262
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800263 if (mFailedPasswordAttempts != 0) {
264 out.startTag(null, "failed-password-attempts");
265 out.attribute(null, "value", Integer.toString(mFailedPasswordAttempts));
266 out.endTag(null, "failed-password-attempts");
267 }
268
Dianne Hackbornd6847842010-01-12 18:14:19 -0800269 out.endDocument();
270 stream.close();
271 journal.commit();
272 } catch (IOException e) {
273 try {
274 if (stream != null) {
275 stream.close();
276 }
277 } catch (IOException ex) {
278 // Ignore
279 }
280 journal.rollback();
281 }
282 }
283
284 private void loadSettingsLocked() {
285 JournaledFile journal = makeJournaledFile();
286 FileInputStream stream = null;
287 File file = journal.chooseForRead();
Dianne Hackbornd6847842010-01-12 18:14:19 -0800288 try {
289 stream = new FileInputStream(file);
290 XmlPullParser parser = Xml.newPullParser();
291 parser.setInput(stream, null);
292
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800293 int type;
294 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
295 && type != XmlPullParser.START_TAG) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800296 }
297 String tag = parser.getName();
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800298 if (!"policies".equals(tag)) {
299 throw new XmlPullParserException(
300 "Settings do not start with policies tag: found " + tag);
301 }
302 type = parser.next();
303 int outerDepth = parser.getDepth();
304 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
305 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
306 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
307 continue;
308 }
309 tag = parser.getName();
310 if ("admin".equals(tag)) {
311 DeviceAdminInfo dai = findAdmin(
312 ComponentName.unflattenFromString(
313 parser.getAttributeValue(null, "name")));
314 if (dai != null) {
315 ActiveAdmin ap = new ActiveAdmin(dai);
316 ap.readFromXml(parser);
317 mActiveAdmin = ap;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800318 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800319 } else if ("failed-password-attempts".equals(tag)) {
320 mFailedPasswordAttempts = Integer.parseInt(
321 parser.getAttributeValue(null, "value"));
322 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800323 }
324 } catch (NullPointerException e) {
325 Log.w(TAG, "failed parsing " + file + " " + e);
326 } catch (NumberFormatException e) {
327 Log.w(TAG, "failed parsing " + file + " " + e);
328 } catch (XmlPullParserException e) {
329 Log.w(TAG, "failed parsing " + file + " " + e);
330 } catch (IOException e) {
331 Log.w(TAG, "failed parsing " + file + " " + e);
332 } catch (IndexOutOfBoundsException e) {
333 Log.w(TAG, "failed parsing " + file + " " + e);
334 }
335 try {
336 if (stream != null) {
337 stream.close();
338 }
339 } catch (IOException e) {
340 // Ignore
341 }
342
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800343 long timeMs = getMaximumTimeToLock();
344 if (timeMs <= 0) {
345 timeMs = Integer.MAX_VALUE;
346 }
347 try {
348 getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
349 } catch (RemoteException e) {
350 Log.w(TAG, "Failure talking with power manager", e);
351 }
352
Dianne Hackbornd6847842010-01-12 18:14:19 -0800353 }
354
355 public void systemReady() {
356 synchronized (this) {
357 loadSettingsLocked();
358 }
359 }
360
361 public void setActiveAdmin(ComponentName adminReceiver) {
362 mContext.enforceCallingOrSelfPermission(
363 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
364
365 DeviceAdminInfo info = findAdmin(adminReceiver);
366 if (info == null) {
367 throw new IllegalArgumentException("Bad admin: " + adminReceiver);
368 }
369 synchronized (this) {
370 long ident = Binder.clearCallingIdentity();
371 try {
372 ComponentName cur = getActiveAdminLocked();
373 if (cur != null && cur.equals(adminReceiver)) {
374 throw new IllegalStateException("An admin is already set");
375 }
376 if (cur != null) {
377 removeActiveAdminLocked(adminReceiver);
378 }
379 mActiveAdmin = new ActiveAdmin(info);
380 saveSettingsLocked();
381 sendAdminCommandLocked(mActiveAdmin,
382 DeviceAdmin.ACTION_DEVICE_ADMIN_ENABLED);
383 } finally {
384 Binder.restoreCallingIdentity(ident);
385 }
386 }
387 }
388
389 public ComponentName getActiveAdmin() {
390 synchronized (this) {
391 return getActiveAdminLocked();
392 }
393 }
394
395 public void removeActiveAdmin(ComponentName adminReceiver) {
396 synchronized (this) {
397 if (mActiveAdmin == null || mActiveAdmin.getUid() != Binder.getCallingUid()) {
398 mContext.enforceCallingOrSelfPermission(
399 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
400 }
401 long ident = Binder.clearCallingIdentity();
402 try {
403 removeActiveAdminLocked(adminReceiver);
404 } finally {
405 Binder.restoreCallingIdentity(ident);
406 }
407 }
408 }
409
410 public void setPasswordMode(ComponentName who, int mode) {
411 synchronized (this) {
412 if (who == null) {
413 throw new NullPointerException("ComponentName is null");
414 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800415 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
416 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800417 if (ap.passwordMode != mode) {
418 ap.passwordMode = mode;
419 saveSettingsLocked();
420 }
421 }
422 }
423
424 public int getPasswordMode() {
425 synchronized (this) {
426 return mActiveAdmin != null ? mActiveAdmin.passwordMode
427 : DevicePolicyManager.PASSWORD_MODE_UNSPECIFIED;
428 }
429 }
430
Dianne Hackbornd6847842010-01-12 18:14:19 -0800431 public void setMinimumPasswordLength(ComponentName who, int length) {
432 synchronized (this) {
433 if (who == null) {
434 throw new NullPointerException("ComponentName is null");
435 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800436 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
437 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800438 if (ap.minimumPasswordLength != length) {
439 ap.minimumPasswordLength = length;
440 saveSettingsLocked();
441 }
442 }
443 }
444
445 public int getMinimumPasswordLength() {
446 synchronized (this) {
447 return mActiveAdmin != null ? mActiveAdmin.minimumPasswordLength : 0;
448 }
449 }
450
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800451 public boolean isActivePasswordSufficient() {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800452 synchronized (this) {
453 // This API can only be called by an active device admin,
454 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800455 getActiveAdminForCallerLocked(null,
456 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800457 return mActivePasswordMode >= getPasswordMode()
458 && mActivePasswordLength >= getMinimumPasswordLength();
Dianne Hackbornd6847842010-01-12 18:14:19 -0800459 }
460 }
461
462 public int getCurrentFailedPasswordAttempts() {
463 synchronized (this) {
464 // This API can only be called by an active device admin,
465 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800466 getActiveAdminForCallerLocked(null,
467 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800468 return mFailedPasswordAttempts;
469 }
470 }
471
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800472 public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) {
473 synchronized (this) {
474 // This API can only be called by an active device admin,
475 // so try to retrieve it to check that the caller is one.
476 getActiveAdminForCallerLocked(who,
477 DeviceAdminInfo.USES_POLICY_WIPE_DATA);
478 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
479 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
480 if (ap.maximumFailedPasswordsForWipe != num) {
481 ap.maximumFailedPasswordsForWipe = num;
482 saveSettingsLocked();
483 }
484 }
485 }
486
487 public int getMaximumFailedPasswordsForWipe() {
488 synchronized (this) {
489 return mActiveAdmin != null ? mActiveAdmin.maximumFailedPasswordsForWipe : 0;
490 }
491 }
492
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800493 public boolean resetPassword(String password) {
494 int mode;
495 synchronized (this) {
496 // This API can only be called by an active device admin,
497 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800498 getActiveAdminForCallerLocked(null,
499 DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800500 mode = getPasswordMode();
501 if (password.length() < getMinimumPasswordLength()) {
502 return false;
503 }
504 }
505
506 // Don't do this with the lock held, because it is going to call
507 // back in to the service.
508 long ident = Binder.clearCallingIdentity();
509 try {
510 LockPatternUtils utils = new LockPatternUtils(mContext);
511 utils.saveLockPassword(password, mode);
512 } finally {
513 Binder.restoreCallingIdentity(ident);
514 }
515
516 return true;
517 }
518
Dianne Hackbornd6847842010-01-12 18:14:19 -0800519 public void setMaximumTimeToLock(ComponentName who, long timeMs) {
520 synchronized (this) {
521 if (who == null) {
522 throw new NullPointerException("ComponentName is null");
523 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800524 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
525 DeviceAdminInfo.USES_POLICY_LIMIT_UNLOCK);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800526 if (ap.maximumTimeToUnlock != timeMs) {
527 ap.maximumTimeToUnlock = timeMs;
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800528
529 long ident = Binder.clearCallingIdentity();
530 try {
531 saveSettingsLocked();
532 if (timeMs <= 0) {
533 timeMs = Integer.MAX_VALUE;
534 }
535 try {
536 getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
537 } catch (RemoteException e) {
538 Log.w(TAG, "Failure talking with power manager", e);
539 }
540 } finally {
541 Binder.restoreCallingIdentity(ident);
542 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800543 }
544 }
545 }
546
547 public long getMaximumTimeToLock() {
548 synchronized (this) {
549 return mActiveAdmin != null ? mActiveAdmin.maximumTimeToUnlock : 0;
550 }
551 }
552
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800553 public void lockNow() {
554 synchronized (this) {
555 // This API can only be called by an active device admin,
556 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800557 getActiveAdminForCallerLocked(null,
558 DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800559 // STOPSHIP need to implement.
560 }
561 }
562
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800563 void wipeDataLocked(int flags) {
564 try {
565 RecoverySystem.rebootWipeUserData(mContext);
566 } catch (IOException e) {
567 Log.w(TAG, "Failed requesting data wipe", e);
568 }
569 }
570
Dianne Hackbornd6847842010-01-12 18:14:19 -0800571 public void wipeData(int flags) {
572 synchronized (this) {
573 // This API can only be called by an active device admin,
574 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800575 getActiveAdminForCallerLocked(null,
576 DeviceAdminInfo.USES_POLICY_WIPE_DATA);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800577 long ident = Binder.clearCallingIdentity();
578 try {
579 wipeDataLocked(flags);
580 } finally {
581 Binder.restoreCallingIdentity(ident);
582 }
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800583 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800584 }
585
586 public void getRemoveWarning(ComponentName comp, final RemoteCallback result) {
587 mContext.enforceCallingOrSelfPermission(
588 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
589
590 synchronized (this) {
591 ActiveAdmin admin = getActiveAdminUncheckedLocked(comp);
592 if (admin == null) {
593 try {
594 result.sendResult(null);
595 } catch (RemoteException e) {
596 }
597 return;
598 }
599 Intent intent = new Intent(DeviceAdmin.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
600 intent.setComponent(admin.info.getComponent());
601 mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
602 @Override
603 public void onReceive(Context context, Intent intent) {
604 try {
605 result.sendResult(getResultExtras(false));
606 } catch (RemoteException e) {
607 }
608 }
609 }, null, Activity.RESULT_OK, null, null);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800610 }
611 }
612
613 public void setActivePasswordState(int mode, int length) {
614 mContext.enforceCallingOrSelfPermission(
615 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
616
617 synchronized (this) {
618 if (mActivePasswordMode != mode || mActivePasswordLength != length
619 || mFailedPasswordAttempts != 0) {
620 long ident = Binder.clearCallingIdentity();
621 try {
622 mActivePasswordMode = mode;
623 mActivePasswordLength = length;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800624 if (mFailedPasswordAttempts != 0) {
625 mFailedPasswordAttempts = 0;
626 saveSettingsLocked();
627 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800628 sendAdminCommandLocked(DeviceAdmin.ACTION_PASSWORD_CHANGED,
629 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800630 } finally {
631 Binder.restoreCallingIdentity(ident);
632 }
633 }
634 }
635 }
636
637 public void reportFailedPasswordAttempt() {
638 mContext.enforceCallingOrSelfPermission(
639 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
640
641 synchronized (this) {
642 long ident = Binder.clearCallingIdentity();
643 try {
644 mFailedPasswordAttempts++;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800645 saveSettingsLocked();
646 int max = getMaximumFailedPasswordsForWipe();
647 if (max > 0 && mFailedPasswordAttempts >= max) {
648 wipeDataLocked(0);
649 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800650 sendAdminCommandLocked(DeviceAdmin.ACTION_PASSWORD_FAILED,
651 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800652 } finally {
653 Binder.restoreCallingIdentity(ident);
654 }
655 }
656 }
657
658 public void reportSuccessfulPasswordAttempt() {
659 mContext.enforceCallingOrSelfPermission(
660 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
661
662 synchronized (this) {
663 if (mFailedPasswordAttempts != 0) {
664 long ident = Binder.clearCallingIdentity();
665 try {
666 mFailedPasswordAttempts = 0;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800667 saveSettingsLocked();
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800668 sendAdminCommandLocked(DeviceAdmin.ACTION_PASSWORD_SUCCEEDED,
669 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800670 } finally {
671 Binder.restoreCallingIdentity(ident);
672 }
673 }
674 }
675 }
676}