blob: 1d715778b2e1128364c06aacfcd2b98cb994ecef [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
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080019import com.android.internal.content.PackageMonitor;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080020import com.android.internal.util.FastXmlSerializer;
Dianne Hackborn1afd1c92010-03-18 22:47:17 -070021import com.android.internal.util.JournaledFile;
Dianne Hackborn2269d1572010-02-24 19:54:22 -080022import com.android.internal.util.XmlUtils;
Dianne Hackborndf83afa2010-01-20 13:37:26 -080023import com.android.internal.widget.LockPatternUtils;
Dianne Hackbornd6847842010-01-12 18:14:19 -080024
25import org.xmlpull.v1.XmlPullParser;
26import org.xmlpull.v1.XmlPullParserException;
27import org.xmlpull.v1.XmlSerializer;
28
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080029import android.app.Activity;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080030import android.app.admin.DeviceAdminInfo;
31import android.app.admin.DeviceAdminReceiver;
32import android.app.admin.DevicePolicyManager;
33import android.app.admin.IDevicePolicyManager;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080034import android.content.BroadcastReceiver;
Dianne Hackbornd6847842010-01-12 18:14:19 -080035import android.content.ComponentName;
36import android.content.Context;
37import android.content.Intent;
38import android.content.pm.PackageManager;
39import android.content.pm.ResolveInfo;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080040import android.content.pm.PackageManager.NameNotFoundException;
Dianne Hackbornd6847842010-01-12 18:14:19 -080041import android.os.Binder;
Dianne Hackborndf83afa2010-01-20 13:37:26 -080042import android.os.IBinder;
43import android.os.IPowerManager;
Dianne Hackborndf83afa2010-01-20 13:37:26 -080044import android.os.RecoverySystem;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080045import android.os.RemoteCallback;
Dianne Hackborndf83afa2010-01-20 13:37:26 -080046import android.os.RemoteException;
47import android.os.ServiceManager;
Dianne Hackborn254cb442010-01-27 19:23:59 -080048import android.os.SystemClock;
Dianne Hackbornd6847842010-01-12 18:14:19 -080049import android.util.Log;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080050import android.util.PrintWriterPrinter;
51import android.util.Printer;
Dianne Hackbornd6847842010-01-12 18:14:19 -080052import android.util.Xml;
Dianne Hackborn254cb442010-01-27 19:23:59 -080053import android.view.WindowManagerPolicy;
Dianne Hackbornd6847842010-01-12 18:14:19 -080054
55import java.io.File;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080056import java.io.FileDescriptor;
Dianne Hackbornd6847842010-01-12 18:14:19 -080057import java.io.FileInputStream;
58import java.io.FileOutputStream;
59import java.io.IOException;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080060import java.io.PrintWriter;
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -080061import java.util.ArrayList;
62import java.util.HashMap;
Dianne Hackbornd6847842010-01-12 18:14:19 -080063import java.util.List;
64
65/**
66 * Implementation of the device policy APIs.
67 */
68public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080069 static final String TAG = "DevicePolicyManagerService";
Dianne Hackbornd6847842010-01-12 18:14:19 -080070
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080071 final Context mContext;
72 final MyPackageMonitor mMonitor;
Dianne Hackbornd6847842010-01-12 18:14:19 -080073
Dianne Hackborndf83afa2010-01-20 13:37:26 -080074 IPowerManager mIPowerManager;
75
Dianne Hackborn9327f4f2010-01-29 10:38:29 -080076 int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
Dianne Hackbornd6847842010-01-12 18:14:19 -080077 int mActivePasswordLength = 0;
78 int mFailedPasswordAttempts = 0;
79
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080080 int mPasswordOwner = -1;
81
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -080082 final HashMap<ComponentName, ActiveAdmin> mAdminMap
83 = new HashMap<ComponentName, ActiveAdmin>();
84 final ArrayList<ActiveAdmin> mAdminList
85 = new ArrayList<ActiveAdmin>();
Dianne Hackbornd6847842010-01-12 18:14:19 -080086
87 static class ActiveAdmin {
Dianne Hackbornd6847842010-01-12 18:14:19 -080088 final DeviceAdminInfo info;
Dianne Hackbornd6847842010-01-12 18:14:19 -080089
Dianne Hackborn9327f4f2010-01-29 10:38:29 -080090 int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
Dianne Hackbornd6847842010-01-12 18:14:19 -080091 int minimumPasswordLength = 0;
92 long maximumTimeToUnlock = 0;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080093 int maximumFailedPasswordsForWipe = 0;
94
95 ActiveAdmin(DeviceAdminInfo _info) {
96 info = _info;
97 }
98
99 int getUid() { return info.getActivityInfo().applicationInfo.uid; }
100
101 void writeToXml(XmlSerializer out)
102 throws IllegalArgumentException, IllegalStateException, IOException {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800103 out.startTag(null, "policies");
104 info.writePoliciesToXml(out);
105 out.endTag(null, "policies");
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800106 if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
107 out.startTag(null, "password-quality");
108 out.attribute(null, "value", Integer.toString(passwordQuality));
109 out.endTag(null, "password-quality");
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800110 if (minimumPasswordLength > 0) {
111 out.startTag(null, "min-password-length");
112 out.attribute(null, "value", Integer.toString(minimumPasswordLength));
113 out.endTag(null, "mn-password-length");
114 }
115 }
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800116 if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800117 out.startTag(null, "max-time-to-unlock");
118 out.attribute(null, "value", Long.toString(maximumTimeToUnlock));
119 out.endTag(null, "max-time-to-unlock");
120 }
121 if (maximumFailedPasswordsForWipe != 0) {
122 out.startTag(null, "max-failed-password-wipe");
123 out.attribute(null, "value", Integer.toString(maximumFailedPasswordsForWipe));
124 out.endTag(null, "max-failed-password-wipe");
125 }
126 }
127
128 void readFromXml(XmlPullParser parser)
129 throws XmlPullParserException, IOException {
130 int outerDepth = parser.getDepth();
131 int type;
132 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
133 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
134 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
135 continue;
136 }
137 String tag = parser.getName();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800138 if ("policies".equals(tag)) {
139 info.readPoliciesFromXml(parser);
140 } else if ("password-quality".equals(tag)) {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800141 passwordQuality = Integer.parseInt(
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800142 parser.getAttributeValue(null, "value"));
143 } else if ("min-password-length".equals(tag)) {
144 minimumPasswordLength = Integer.parseInt(
145 parser.getAttributeValue(null, "value"));
146 } else if ("max-time-to-unlock".equals(tag)) {
147 maximumTimeToUnlock = Long.parseLong(
148 parser.getAttributeValue(null, "value"));
149 } else if ("max-failed-password-wipe".equals(tag)) {
150 maximumFailedPasswordsForWipe = Integer.parseInt(
151 parser.getAttributeValue(null, "value"));
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800152 } else {
153 Log.w(TAG, "Unknown admin tag: " + tag);
154 }
155 XmlUtils.skipCurrentTag(parser);
156 }
157 }
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800158
159 void dump(String prefix, PrintWriter pw) {
160 pw.print(prefix); pw.print("uid="); pw.println(getUid());
161 pw.print(prefix); pw.println("policies:");
162 ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies();
163 if (pols != null) {
164 for (int i=0; i<pols.size(); i++) {
165 pw.print(prefix); pw.print(" "); pw.println(pols.get(i).tag);
166 }
167 }
168 pw.print(prefix); pw.print("passwordQuality=");
169 pw.print(passwordQuality);
170 pw.print(" minimumPasswordLength=");
171 pw.println(minimumPasswordLength);
172 pw.print(prefix); pw.print("maximumTimeToUnlock=");
173 pw.println(maximumTimeToUnlock);
174 pw.print(prefix); pw.print("maximumFailedPasswordsForWipe=");
175 pw.println(maximumFailedPasswordsForWipe);
176 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800177 }
178
179 class MyPackageMonitor extends PackageMonitor {
180 public void onSomePackagesChanged() {
181 synchronized (DevicePolicyManagerService.this) {
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800182 boolean removed = false;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800183 for (int i=mAdminList.size()-1; i>=0; i--) {
184 ActiveAdmin aa = mAdminList.get(i);
185 int change = isPackageDisappearing(aa.info.getPackageName());
186 if (change == PACKAGE_PERMANENT_CHANGE
187 || change == PACKAGE_TEMPORARY_CHANGE) {
188 Log.w(TAG, "Admin unexpectedly uninstalled: "
189 + aa.info.getComponent());
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800190 removed = true;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800191 mAdminList.remove(i);
192 } else if (isPackageModified(aa.info.getPackageName())) {
193 try {
194 mContext.getPackageManager().getReceiverInfo(
195 aa.info.getComponent(), 0);
196 } catch (NameNotFoundException e) {
197 Log.w(TAG, "Admin package change removed component: "
198 + aa.info.getComponent());
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800199 removed = true;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800200 mAdminList.remove(i);
201 }
202 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800203 }
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800204 if (removed) {
205 validatePasswordOwnerLocked();
206 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800207 }
208 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800209 }
210
211 /**
212 * Instantiates the service.
213 */
214 public DevicePolicyManagerService(Context context) {
215 mContext = context;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800216 mMonitor = new MyPackageMonitor();
217 mMonitor.register(context, true);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800218 }
219
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800220 private IPowerManager getIPowerManager() {
221 if (mIPowerManager == null) {
222 IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
223 mIPowerManager = IPowerManager.Stub.asInterface(b);
224 }
225 return mIPowerManager;
226 }
227
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800228 ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800229 ActiveAdmin admin = mAdminMap.get(who);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800230 if (admin != null
231 && who.getPackageName().equals(admin.info.getActivityInfo().packageName)
232 && who.getClassName().equals(admin.info.getActivityInfo().name)) {
233 return admin;
234 }
235 return null;
236 }
237
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800238 ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
239 throws SecurityException {
Dianne Hackborn254cb442010-01-27 19:23:59 -0800240 final int callingUid = Binder.getCallingUid();
241 if (who != null) {
242 ActiveAdmin admin = mAdminMap.get(who);
243 if (admin == null) {
244 throw new SecurityException("No active admin " + who);
245 }
246 if (admin.getUid() != callingUid) {
247 throw new SecurityException("Admin " + who + " is not owned by uid "
248 + Binder.getCallingUid());
249 }
250 if (!admin.info.usesPolicy(reqPolicy)) {
251 throw new SecurityException("Admin " + admin.info.getComponent()
252 + " did not specify uses-policy for: "
253 + admin.info.getTagForPolicy(reqPolicy));
254 }
255 return admin;
256 } else {
257 final int N = mAdminList.size();
258 for (int i=0; i<N; i++) {
259 ActiveAdmin admin = mAdminList.get(i);
260 if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) {
261 return admin;
262 }
263 }
264 throw new SecurityException("No active admin owned by uid "
265 + Binder.getCallingUid() + " for policy #" + reqPolicy);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800266 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800267 }
268
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800269 void sendAdminCommandLocked(ActiveAdmin admin, String action) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800270 Intent intent = new Intent(action);
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800271 intent.setComponent(admin.info.getComponent());
Dianne Hackbornd6847842010-01-12 18:14:19 -0800272 mContext.sendBroadcast(intent);
273 }
274
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800275 void sendAdminCommandLocked(String action, int reqPolicy) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800276 final int N = mAdminList.size();
277 if (N > 0) {
278 for (int i=0; i<N; i++) {
279 ActiveAdmin admin = mAdminList.get(i);
280 if (admin.info.usesPolicy(reqPolicy)) {
281 sendAdminCommandLocked(admin, action);
282 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800283 }
Dianne Hackborn4141d032010-01-21 16:29:00 -0800284 }
285 }
286
Dianne Hackbornd6847842010-01-12 18:14:19 -0800287 void removeActiveAdminLocked(ComponentName adminReceiver) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800288 ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
289 if (admin != null) {
290 sendAdminCommandLocked(admin,
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800291 DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800292 // XXX need to wait for it to complete.
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800293 mAdminList.remove(admin);
294 mAdminMap.remove(adminReceiver);
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800295 validatePasswordOwnerLocked();
Dianne Hackbornd6847842010-01-12 18:14:19 -0800296 }
297 }
298
299 public DeviceAdminInfo findAdmin(ComponentName adminName) {
300 Intent resolveIntent = new Intent();
301 resolveIntent.setComponent(adminName);
302 List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceivers(
303 resolveIntent, PackageManager.GET_META_DATA);
304 if (infos == null || infos.size() <= 0) {
305 throw new IllegalArgumentException("Unknown admin: " + adminName);
306 }
307
308 try {
309 return new DeviceAdminInfo(mContext, infos.get(0));
310 } catch (XmlPullParserException e) {
311 Log.w(TAG, "Bad device admin requested: " + adminName, e);
312 return null;
313 } catch (IOException e) {
314 Log.w(TAG, "Bad device admin requested: " + adminName, e);
315 return null;
316 }
317 }
318
319 private static JournaledFile makeJournaledFile() {
320 final String base = "/data/system/device_policies.xml";
321 return new JournaledFile(new File(base), new File(base + ".tmp"));
322 }
323
324 private void saveSettingsLocked() {
325 JournaledFile journal = makeJournaledFile();
326 FileOutputStream stream = null;
327 try {
328 stream = new FileOutputStream(journal.chooseForWrite(), false);
329 XmlSerializer out = new FastXmlSerializer();
330 out.setOutput(stream, "utf-8");
331 out.startDocument(null, true);
332
333 out.startTag(null, "policies");
334
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800335 final int N = mAdminList.size();
336 for (int i=0; i<N; i++) {
337 ActiveAdmin ap = mAdminList.get(i);
338 if (ap != null) {
339 out.startTag(null, "admin");
340 out.attribute(null, "name", ap.info.getComponent().flattenToString());
341 ap.writeToXml(out);
342 out.endTag(null, "admin");
343 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800344 }
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800345
Dianne Hackbornd6847842010-01-12 18:14:19 -0800346 out.endTag(null, "policies");
347
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800348 if (mPasswordOwner >= 0) {
349 out.startTag(null, "password-owner");
350 out.attribute(null, "value", Integer.toString(mPasswordOwner));
351 out.endTag(null, "password-owner");
352 }
353
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800354 if (mFailedPasswordAttempts != 0) {
355 out.startTag(null, "failed-password-attempts");
356 out.attribute(null, "value", Integer.toString(mFailedPasswordAttempts));
357 out.endTag(null, "failed-password-attempts");
358 }
359
Dianne Hackbornd6847842010-01-12 18:14:19 -0800360 out.endDocument();
361 stream.close();
362 journal.commit();
363 } catch (IOException e) {
364 try {
365 if (stream != null) {
366 stream.close();
367 }
368 } catch (IOException ex) {
369 // Ignore
370 }
371 journal.rollback();
372 }
373 }
374
375 private void loadSettingsLocked() {
376 JournaledFile journal = makeJournaledFile();
377 FileInputStream stream = null;
378 File file = journal.chooseForRead();
Dianne Hackbornd6847842010-01-12 18:14:19 -0800379 try {
380 stream = new FileInputStream(file);
381 XmlPullParser parser = Xml.newPullParser();
382 parser.setInput(stream, null);
383
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800384 int type;
385 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
386 && type != XmlPullParser.START_TAG) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800387 }
388 String tag = parser.getName();
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800389 if (!"policies".equals(tag)) {
390 throw new XmlPullParserException(
391 "Settings do not start with policies tag: found " + tag);
392 }
393 type = parser.next();
394 int outerDepth = parser.getDepth();
395 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
396 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
397 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
398 continue;
399 }
400 tag = parser.getName();
401 if ("admin".equals(tag)) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800402 String name = parser.getAttributeValue(null, "name");
403 try {
404 DeviceAdminInfo dai = findAdmin(
405 ComponentName.unflattenFromString(name));
406 if (dai != null) {
407 ActiveAdmin ap = new ActiveAdmin(dai);
408 ap.readFromXml(parser);
409 mAdminMap.put(ap.info.getComponent(), ap);
410 mAdminList.add(ap);
411 }
412 } catch (RuntimeException e) {
413 Log.w(TAG, "Failed loading admin " + name, e);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800414 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800415 } else if ("failed-password-attempts".equals(tag)) {
416 mFailedPasswordAttempts = Integer.parseInt(
417 parser.getAttributeValue(null, "value"));
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800418 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800419 } else if ("password-owner".equals(tag)) {
420 mPasswordOwner = Integer.parseInt(
421 parser.getAttributeValue(null, "value"));
422 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800423 } else {
424 Log.w(TAG, "Unknown tag: " + tag);
425 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800426 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800427 }
428 } catch (NullPointerException e) {
429 Log.w(TAG, "failed parsing " + file + " " + e);
430 } catch (NumberFormatException e) {
431 Log.w(TAG, "failed parsing " + file + " " + e);
432 } catch (XmlPullParserException e) {
433 Log.w(TAG, "failed parsing " + file + " " + e);
434 } catch (IOException e) {
435 Log.w(TAG, "failed parsing " + file + " " + e);
436 } catch (IndexOutOfBoundsException e) {
437 Log.w(TAG, "failed parsing " + file + " " + e);
438 }
439 try {
440 if (stream != null) {
441 stream.close();
442 }
443 } catch (IOException e) {
444 // Ignore
445 }
446
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800447 validatePasswordOwnerLocked();
448
Dianne Hackborn254cb442010-01-27 19:23:59 -0800449 long timeMs = getMaximumTimeToLock(null);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800450 if (timeMs <= 0) {
451 timeMs = Integer.MAX_VALUE;
452 }
453 try {
454 getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
455 } catch (RemoteException e) {
456 Log.w(TAG, "Failure talking with power manager", e);
457 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800458 }
459
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800460 void validatePasswordOwnerLocked() {
461 if (mPasswordOwner >= 0) {
462 boolean haveOwner = false;
463 for (int i=mAdminList.size()-1; i>=0; i--) {
464 if (mAdminList.get(i).getUid() == mPasswordOwner) {
465 haveOwner = true;
466 break;
467 }
468 }
469 if (!haveOwner) {
470 Log.w(TAG, "Previous password owner " + mPasswordOwner
471 + " no longer active; disabling");
472 mPasswordOwner = -1;
473 }
474 }
475 }
476
Dianne Hackbornd6847842010-01-12 18:14:19 -0800477 public void systemReady() {
478 synchronized (this) {
479 loadSettingsLocked();
480 }
481 }
482
483 public void setActiveAdmin(ComponentName adminReceiver) {
484 mContext.enforceCallingOrSelfPermission(
485 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
486
487 DeviceAdminInfo info = findAdmin(adminReceiver);
488 if (info == null) {
489 throw new IllegalArgumentException("Bad admin: " + adminReceiver);
490 }
491 synchronized (this) {
492 long ident = Binder.clearCallingIdentity();
493 try {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800494 if (getActiveAdminUncheckedLocked(adminReceiver) != null) {
495 throw new IllegalArgumentException("Admin is already added");
Dianne Hackbornd6847842010-01-12 18:14:19 -0800496 }
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800497 ActiveAdmin admin = new ActiveAdmin(info);
498 mAdminMap.put(adminReceiver, admin);
499 mAdminList.add(admin);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800500 saveSettingsLocked();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800501 sendAdminCommandLocked(admin,
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800502 DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800503 } finally {
504 Binder.restoreCallingIdentity(ident);
505 }
506 }
507 }
508
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800509 public boolean isAdminActive(ComponentName adminReceiver) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800510 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800511 return getActiveAdminUncheckedLocked(adminReceiver) != null;
512 }
513 }
514
515 public List<ComponentName> getActiveAdmins() {
516 synchronized (this) {
517 final int N = mAdminList.size();
518 if (N <= 0) {
519 return null;
520 }
521 ArrayList<ComponentName> res = new ArrayList<ComponentName>(N);
522 for (int i=0; i<N; i++) {
523 res.add(mAdminList.get(i).info.getComponent());
524 }
525 return res;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800526 }
527 }
528
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800529 public boolean packageHasActiveAdmins(String packageName) {
530 synchronized (this) {
531 final int N = mAdminList.size();
532 for (int i=0; i<N; i++) {
533 if (mAdminList.get(i).info.getPackageName().equals(packageName)) {
534 return true;
535 }
536 }
537 return false;
538 }
539 }
540
Dianne Hackbornd6847842010-01-12 18:14:19 -0800541 public void removeActiveAdmin(ComponentName adminReceiver) {
542 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800543 ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
544 if (admin == null) {
545 return;
546 }
547 if (admin.getUid() != Binder.getCallingUid()) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800548 mContext.enforceCallingOrSelfPermission(
549 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
550 }
551 long ident = Binder.clearCallingIdentity();
552 try {
553 removeActiveAdminLocked(adminReceiver);
554 } finally {
555 Binder.restoreCallingIdentity(ident);
556 }
557 }
558 }
559
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800560 public void setPasswordQuality(ComponentName who, int mode) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800561 synchronized (this) {
562 if (who == null) {
563 throw new NullPointerException("ComponentName is null");
564 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800565 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
566 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800567 if (ap.passwordQuality != mode) {
568 ap.passwordQuality = mode;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800569 saveSettingsLocked();
570 }
571 }
572 }
573
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800574 public int getPasswordQuality(ComponentName who) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800575 synchronized (this) {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800576 int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
Dianne Hackborn254cb442010-01-27 19:23:59 -0800577
578 if (who != null) {
579 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800580 return admin != null ? admin.passwordQuality : mode;
Dianne Hackborn254cb442010-01-27 19:23:59 -0800581 }
582
583 final int N = mAdminList.size();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800584 for (int i=0; i<N; i++) {
585 ActiveAdmin admin = mAdminList.get(i);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800586 if (mode < admin.passwordQuality) {
587 mode = admin.passwordQuality;
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800588 }
589 }
590 return mode;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800591 }
592 }
593
Dianne Hackborn254cb442010-01-27 19:23:59 -0800594 public void setPasswordMinimumLength(ComponentName who, int length) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800595 synchronized (this) {
596 if (who == null) {
597 throw new NullPointerException("ComponentName is null");
598 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800599 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
600 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800601 if (ap.minimumPasswordLength != length) {
602 ap.minimumPasswordLength = length;
603 saveSettingsLocked();
604 }
605 }
606 }
607
Dianne Hackborn254cb442010-01-27 19:23:59 -0800608 public int getPasswordMinimumLength(ComponentName who) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800609 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800610 int length = 0;
Dianne Hackborn254cb442010-01-27 19:23:59 -0800611
612 if (who != null) {
613 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
614 return admin != null ? admin.minimumPasswordLength : length;
615 }
616
617 final int N = mAdminList.size();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800618 for (int i=0; i<N; i++) {
619 ActiveAdmin admin = mAdminList.get(i);
620 if (length < admin.minimumPasswordLength) {
621 length = admin.minimumPasswordLength;
622 }
623 }
624 return length;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800625 }
626 }
627
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800628 public boolean isActivePasswordSufficient() {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800629 synchronized (this) {
630 // This API can only be called by an active device admin,
631 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800632 getActiveAdminForCallerLocked(null,
633 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800634 return mActivePasswordQuality >= getPasswordQuality(null)
Dianne Hackborn254cb442010-01-27 19:23:59 -0800635 && mActivePasswordLength >= getPasswordMinimumLength(null);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800636 }
637 }
638
639 public int getCurrentFailedPasswordAttempts() {
640 synchronized (this) {
641 // This API can only be called by an active device admin,
642 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800643 getActiveAdminForCallerLocked(null,
644 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800645 return mFailedPasswordAttempts;
646 }
647 }
648
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800649 public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) {
650 synchronized (this) {
651 // This API can only be called by an active device admin,
652 // so try to retrieve it to check that the caller is one.
653 getActiveAdminForCallerLocked(who,
654 DeviceAdminInfo.USES_POLICY_WIPE_DATA);
655 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
656 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
657 if (ap.maximumFailedPasswordsForWipe != num) {
658 ap.maximumFailedPasswordsForWipe = num;
659 saveSettingsLocked();
660 }
661 }
662 }
663
Dianne Hackborn254cb442010-01-27 19:23:59 -0800664 public int getMaximumFailedPasswordsForWipe(ComponentName who) {
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800665 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800666 int count = 0;
Dianne Hackborn254cb442010-01-27 19:23:59 -0800667
668 if (who != null) {
669 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
670 return admin != null ? admin.maximumFailedPasswordsForWipe : count;
671 }
672
673 final int N = mAdminList.size();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800674 for (int i=0; i<N; i++) {
675 ActiveAdmin admin = mAdminList.get(i);
676 if (count == 0) {
677 count = admin.maximumFailedPasswordsForWipe;
678 } else if (admin.maximumFailedPasswordsForWipe != 0
679 && count > admin.maximumFailedPasswordsForWipe) {
680 count = admin.maximumFailedPasswordsForWipe;
681 }
682 }
683 return count;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800684 }
685 }
686
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800687 public boolean resetPassword(String password, int flags) {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800688 int quality;
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800689 synchronized (this) {
690 // This API can only be called by an active device admin,
691 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800692 getActiveAdminForCallerLocked(null,
693 DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800694 quality = getPasswordQuality(null);
695 if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
696 int adjQuality = LockPatternUtils.adjustPasswordMode(password, quality);
697 if (adjQuality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
698 Log.w(TAG, "resetPassword: password does not meet quality " + quality);
699 return false;
700 }
701 quality = adjQuality;
702 }
703 int length = getPasswordMinimumLength(null);
704 if (password.length() < length) {
705 Log.w(TAG, "resetPassword: password does not meet length " + length);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800706 return false;
707 }
708 }
709
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800710 int callingUid = Binder.getCallingUid();
711 if (mPasswordOwner >= 0 && mPasswordOwner != callingUid) {
712 Log.w(TAG, "resetPassword: already set by another uid and not entered by user");
713 return false;
714 }
715
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800716 // Don't do this with the lock held, because it is going to call
717 // back in to the service.
718 long ident = Binder.clearCallingIdentity();
719 try {
720 LockPatternUtils utils = new LockPatternUtils(mContext);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800721 utils.saveLockPassword(password, quality);
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800722 int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY)
723 != 0 ? callingUid : -1;
724 if (mPasswordOwner != newOwner) {
725 mPasswordOwner = newOwner;
726 saveSettingsLocked();
727 }
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800728 } finally {
729 Binder.restoreCallingIdentity(ident);
730 }
731
732 return true;
733 }
734
Dianne Hackbornd6847842010-01-12 18:14:19 -0800735 public void setMaximumTimeToLock(ComponentName who, long timeMs) {
736 synchronized (this) {
737 if (who == null) {
738 throw new NullPointerException("ComponentName is null");
739 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800740 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
Dianne Hackborn315ada72010-02-11 12:14:08 -0800741 DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800742 if (ap.maximumTimeToUnlock != timeMs) {
743 ap.maximumTimeToUnlock = timeMs;
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800744
745 long ident = Binder.clearCallingIdentity();
746 try {
747 saveSettingsLocked();
Dianne Hackborn254cb442010-01-27 19:23:59 -0800748
749 timeMs = getMaximumTimeToLock(null);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800750 if (timeMs <= 0) {
751 timeMs = Integer.MAX_VALUE;
752 }
Dianne Hackborn254cb442010-01-27 19:23:59 -0800753
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800754 try {
755 getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
756 } catch (RemoteException e) {
757 Log.w(TAG, "Failure talking with power manager", e);
758 }
759 } finally {
760 Binder.restoreCallingIdentity(ident);
761 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800762 }
763 }
764 }
765
Dianne Hackborn254cb442010-01-27 19:23:59 -0800766 public long getMaximumTimeToLock(ComponentName who) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800767 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800768 long time = 0;
Dianne Hackborn254cb442010-01-27 19:23:59 -0800769
770 if (who != null) {
771 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
772 return admin != null ? admin.maximumTimeToUnlock : time;
773 }
774
775 final int N = mAdminList.size();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800776 for (int i=0; i<N; i++) {
777 ActiveAdmin admin = mAdminList.get(i);
778 if (time == 0) {
779 time = admin.maximumTimeToUnlock;
780 } else if (admin.maximumTimeToUnlock != 0
781 && time > admin.maximumTimeToUnlock) {
782 time = admin.maximumTimeToUnlock;
783 }
784 }
785 return time;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800786 }
787 }
788
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800789 public void lockNow() {
790 synchronized (this) {
791 // This API can only be called by an active device admin,
792 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800793 getActiveAdminForCallerLocked(null,
794 DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
Dianne Hackborn254cb442010-01-27 19:23:59 -0800795 long ident = Binder.clearCallingIdentity();
796 try {
797 mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(),
798 WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN);
799 } catch (RemoteException e) {
800 } finally {
801 Binder.restoreCallingIdentity(ident);
802 }
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800803 }
804 }
805
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800806 void wipeDataLocked(int flags) {
807 try {
808 RecoverySystem.rebootWipeUserData(mContext);
809 } catch (IOException e) {
810 Log.w(TAG, "Failed requesting data wipe", e);
811 }
812 }
813
Dianne Hackbornd6847842010-01-12 18:14:19 -0800814 public void wipeData(int flags) {
815 synchronized (this) {
816 // This API can only be called by an active device admin,
817 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800818 getActiveAdminForCallerLocked(null,
819 DeviceAdminInfo.USES_POLICY_WIPE_DATA);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800820 long ident = Binder.clearCallingIdentity();
821 try {
822 wipeDataLocked(flags);
823 } finally {
824 Binder.restoreCallingIdentity(ident);
825 }
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800826 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800827 }
828
829 public void getRemoveWarning(ComponentName comp, final RemoteCallback result) {
830 mContext.enforceCallingOrSelfPermission(
831 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
832
833 synchronized (this) {
834 ActiveAdmin admin = getActiveAdminUncheckedLocked(comp);
835 if (admin == null) {
836 try {
837 result.sendResult(null);
838 } catch (RemoteException e) {
839 }
840 return;
841 }
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800842 Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800843 intent.setComponent(admin.info.getComponent());
844 mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
845 @Override
846 public void onReceive(Context context, Intent intent) {
847 try {
848 result.sendResult(getResultExtras(false));
849 } catch (RemoteException e) {
850 }
851 }
852 }, null, Activity.RESULT_OK, null, null);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800853 }
854 }
855
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800856 public void setActivePasswordState(int quality, int length) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800857 mContext.enforceCallingOrSelfPermission(
858 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
859
860 synchronized (this) {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800861 if (mActivePasswordQuality != quality || mActivePasswordLength != length
Dianne Hackbornd6847842010-01-12 18:14:19 -0800862 || mFailedPasswordAttempts != 0) {
863 long ident = Binder.clearCallingIdentity();
864 try {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800865 mActivePasswordQuality = quality;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800866 mActivePasswordLength = length;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800867 if (mFailedPasswordAttempts != 0) {
868 mFailedPasswordAttempts = 0;
869 saveSettingsLocked();
870 }
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800871 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800872 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800873 } finally {
874 Binder.restoreCallingIdentity(ident);
875 }
876 }
877 }
878 }
879
880 public void reportFailedPasswordAttempt() {
881 mContext.enforceCallingOrSelfPermission(
882 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
883
884 synchronized (this) {
885 long ident = Binder.clearCallingIdentity();
886 try {
887 mFailedPasswordAttempts++;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800888 saveSettingsLocked();
Dianne Hackborn254cb442010-01-27 19:23:59 -0800889 int max = getMaximumFailedPasswordsForWipe(null);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800890 if (max > 0 && mFailedPasswordAttempts >= max) {
891 wipeDataLocked(0);
892 }
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800893 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800894 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800895 } finally {
896 Binder.restoreCallingIdentity(ident);
897 }
898 }
899 }
900
901 public void reportSuccessfulPasswordAttempt() {
902 mContext.enforceCallingOrSelfPermission(
903 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
904
905 synchronized (this) {
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800906 if (mFailedPasswordAttempts != 0 || mPasswordOwner >= 0) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800907 long ident = Binder.clearCallingIdentity();
908 try {
909 mFailedPasswordAttempts = 0;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800910 mPasswordOwner = -1;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800911 saveSettingsLocked();
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800912 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800913 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800914 } finally {
915 Binder.restoreCallingIdentity(ident);
916 }
917 }
918 }
919 }
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800920
921 @Override
922 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
923 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
924 != PackageManager.PERMISSION_GRANTED) {
925
926 pw.println("Permission Denial: can't dump DevicePolicyManagerService from from pid="
927 + Binder.getCallingPid()
928 + ", uid=" + Binder.getCallingUid());
929 return;
930 }
931
932 final Printer p = new PrintWriterPrinter(pw);
933
934 synchronized (this) {
935 p.println("Current Device Policy Manager state:");
936
937 p.println(" Enabled Device Admins:");
938 final int N = mAdminList.size();
939 for (int i=0; i<N; i++) {
940 ActiveAdmin ap = mAdminList.get(i);
941 if (ap != null) {
942 pw.print(" "); pw.print(ap.info.getComponent().flattenToShortString());
943 pw.println(":");
944 ap.dump(" ", pw);
945 }
946 }
947
948 pw.println(" ");
949 pw.print(" mActivePasswordQuality="); pw.println(mActivePasswordQuality);
950 pw.print(" mActivePasswordLength="); pw.println(mActivePasswordLength);
951 pw.print(" mFailedPasswordAttempts="); pw.println(mFailedPasswordAttempts);
952 pw.print(" mPasswordOwner="); pw.println(mPasswordOwner);
953 }
954 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800955}