blob: a555244150e054506d30d787540ce1469b9a2584 [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;
21import com.android.internal.util.XmlUtils;
Dianne Hackborndf83afa2010-01-20 13:37:26 -080022import com.android.internal.widget.LockPatternUtils;
Dianne Hackbornd6847842010-01-12 18:14:19 -080023
24import org.xmlpull.v1.XmlPullParser;
25import org.xmlpull.v1.XmlPullParserException;
26import org.xmlpull.v1.XmlSerializer;
27
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080028import android.app.Activity;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080029import android.app.admin.DeviceAdminInfo;
30import android.app.admin.DeviceAdminReceiver;
31import android.app.admin.DevicePolicyManager;
32import android.app.admin.IDevicePolicyManager;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080033import android.content.BroadcastReceiver;
Dianne Hackbornd6847842010-01-12 18:14:19 -080034import android.content.ComponentName;
35import android.content.Context;
36import android.content.Intent;
37import android.content.pm.PackageManager;
38import android.content.pm.ResolveInfo;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080039import android.content.pm.PackageManager.NameNotFoundException;
Dianne Hackbornd6847842010-01-12 18:14:19 -080040import android.os.Binder;
Dianne Hackborndf83afa2010-01-20 13:37:26 -080041import android.os.IBinder;
42import android.os.IPowerManager;
Dianne Hackborndf83afa2010-01-20 13:37:26 -080043import android.os.RecoverySystem;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080044import android.os.RemoteCallback;
Dianne Hackborndf83afa2010-01-20 13:37:26 -080045import android.os.RemoteException;
46import android.os.ServiceManager;
Dianne Hackborn254cb442010-01-27 19:23:59 -080047import android.os.SystemClock;
Dianne Hackbornd6847842010-01-12 18:14:19 -080048import android.util.Log;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080049import android.util.PrintWriterPrinter;
50import android.util.Printer;
Dianne Hackbornd6847842010-01-12 18:14:19 -080051import android.util.Xml;
Dianne Hackborn254cb442010-01-27 19:23:59 -080052import android.view.WindowManagerPolicy;
Dianne Hackbornd6847842010-01-12 18:14:19 -080053
54import java.io.File;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080055import java.io.FileDescriptor;
Dianne Hackbornd6847842010-01-12 18:14:19 -080056import java.io.FileInputStream;
57import java.io.FileOutputStream;
58import java.io.IOException;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080059import java.io.PrintWriter;
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -080060import java.util.ArrayList;
61import java.util.HashMap;
Dianne Hackbornd6847842010-01-12 18:14:19 -080062import java.util.List;
63
64/**
65 * Implementation of the device policy APIs.
66 */
67public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080068 static final String TAG = "DevicePolicyManagerService";
Dianne Hackbornd6847842010-01-12 18:14:19 -080069
Dianne Hackborn21f1bd12010-02-19 17:02:21 -080070 final Context mContext;
71 final MyPackageMonitor mMonitor;
Dianne Hackbornd6847842010-01-12 18:14:19 -080072
Dianne Hackborndf83afa2010-01-20 13:37:26 -080073 IPowerManager mIPowerManager;
74
Dianne Hackborn9327f4f2010-01-29 10:38:29 -080075 int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
Dianne Hackbornd6847842010-01-12 18:14:19 -080076 int mActivePasswordLength = 0;
77 int mFailedPasswordAttempts = 0;
78
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080079 int mPasswordOwner = -1;
80
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -080081 final HashMap<ComponentName, ActiveAdmin> mAdminMap
82 = new HashMap<ComponentName, ActiveAdmin>();
83 final ArrayList<ActiveAdmin> mAdminList
84 = new ArrayList<ActiveAdmin>();
Dianne Hackbornd6847842010-01-12 18:14:19 -080085
86 static class ActiveAdmin {
Dianne Hackbornd6847842010-01-12 18:14:19 -080087 final DeviceAdminInfo info;
Dianne Hackbornd6847842010-01-12 18:14:19 -080088
Dianne Hackborn9327f4f2010-01-29 10:38:29 -080089 int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
Dianne Hackbornd6847842010-01-12 18:14:19 -080090 int minimumPasswordLength = 0;
91 long maximumTimeToUnlock = 0;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080092 int maximumFailedPasswordsForWipe = 0;
93
94 ActiveAdmin(DeviceAdminInfo _info) {
95 info = _info;
96 }
97
98 int getUid() { return info.getActivityInfo().applicationInfo.uid; }
99
100 void writeToXml(XmlSerializer out)
101 throws IllegalArgumentException, IllegalStateException, IOException {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800102 out.startTag(null, "policies");
103 info.writePoliciesToXml(out);
104 out.endTag(null, "policies");
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800105 if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
106 out.startTag(null, "password-quality");
107 out.attribute(null, "value", Integer.toString(passwordQuality));
108 out.endTag(null, "password-quality");
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800109 if (minimumPasswordLength > 0) {
110 out.startTag(null, "min-password-length");
111 out.attribute(null, "value", Integer.toString(minimumPasswordLength));
112 out.endTag(null, "mn-password-length");
113 }
114 }
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800115 if (maximumTimeToUnlock != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800116 out.startTag(null, "max-time-to-unlock");
117 out.attribute(null, "value", Long.toString(maximumTimeToUnlock));
118 out.endTag(null, "max-time-to-unlock");
119 }
120 if (maximumFailedPasswordsForWipe != 0) {
121 out.startTag(null, "max-failed-password-wipe");
122 out.attribute(null, "value", Integer.toString(maximumFailedPasswordsForWipe));
123 out.endTag(null, "max-failed-password-wipe");
124 }
125 }
126
127 void readFromXml(XmlPullParser parser)
128 throws XmlPullParserException, IOException {
129 int outerDepth = parser.getDepth();
130 int type;
131 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
132 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
133 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
134 continue;
135 }
136 String tag = parser.getName();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800137 if ("policies".equals(tag)) {
138 info.readPoliciesFromXml(parser);
139 } else if ("password-quality".equals(tag)) {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800140 passwordQuality = Integer.parseInt(
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800141 parser.getAttributeValue(null, "value"));
142 } else if ("min-password-length".equals(tag)) {
143 minimumPasswordLength = Integer.parseInt(
144 parser.getAttributeValue(null, "value"));
145 } else if ("max-time-to-unlock".equals(tag)) {
146 maximumTimeToUnlock = Long.parseLong(
147 parser.getAttributeValue(null, "value"));
148 } else if ("max-failed-password-wipe".equals(tag)) {
149 maximumFailedPasswordsForWipe = Integer.parseInt(
150 parser.getAttributeValue(null, "value"));
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800151 } else {
152 Log.w(TAG, "Unknown admin tag: " + tag);
153 }
154 XmlUtils.skipCurrentTag(parser);
155 }
156 }
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800157
158 void dump(String prefix, PrintWriter pw) {
159 pw.print(prefix); pw.print("uid="); pw.println(getUid());
160 pw.print(prefix); pw.println("policies:");
161 ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies();
162 if (pols != null) {
163 for (int i=0; i<pols.size(); i++) {
164 pw.print(prefix); pw.print(" "); pw.println(pols.get(i).tag);
165 }
166 }
167 pw.print(prefix); pw.print("passwordQuality=");
168 pw.print(passwordQuality);
169 pw.print(" minimumPasswordLength=");
170 pw.println(minimumPasswordLength);
171 pw.print(prefix); pw.print("maximumTimeToUnlock=");
172 pw.println(maximumTimeToUnlock);
173 pw.print(prefix); pw.print("maximumFailedPasswordsForWipe=");
174 pw.println(maximumFailedPasswordsForWipe);
175 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800176 }
177
178 class MyPackageMonitor extends PackageMonitor {
179 public void onSomePackagesChanged() {
180 synchronized (DevicePolicyManagerService.this) {
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800181 boolean removed = false;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800182 for (int i=mAdminList.size()-1; i>=0; i--) {
183 ActiveAdmin aa = mAdminList.get(i);
184 int change = isPackageDisappearing(aa.info.getPackageName());
185 if (change == PACKAGE_PERMANENT_CHANGE
186 || change == PACKAGE_TEMPORARY_CHANGE) {
187 Log.w(TAG, "Admin unexpectedly uninstalled: "
188 + aa.info.getComponent());
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800189 removed = true;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800190 mAdminList.remove(i);
191 } else if (isPackageModified(aa.info.getPackageName())) {
192 try {
193 mContext.getPackageManager().getReceiverInfo(
194 aa.info.getComponent(), 0);
195 } catch (NameNotFoundException e) {
196 Log.w(TAG, "Admin package change removed component: "
197 + aa.info.getComponent());
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800198 removed = true;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800199 mAdminList.remove(i);
200 }
201 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800202 }
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800203 if (removed) {
204 validatePasswordOwnerLocked();
205 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800206 }
207 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800208 }
209
210 /**
211 * Instantiates the service.
212 */
213 public DevicePolicyManagerService(Context context) {
214 mContext = context;
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800215 mMonitor = new MyPackageMonitor();
216 mMonitor.register(context, true);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800217 }
218
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800219 private IPowerManager getIPowerManager() {
220 if (mIPowerManager == null) {
221 IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
222 mIPowerManager = IPowerManager.Stub.asInterface(b);
223 }
224 return mIPowerManager;
225 }
226
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800227 ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800228 ActiveAdmin admin = mAdminMap.get(who);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800229 if (admin != null
230 && who.getPackageName().equals(admin.info.getActivityInfo().packageName)
231 && who.getClassName().equals(admin.info.getActivityInfo().name)) {
232 return admin;
233 }
234 return null;
235 }
236
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800237 ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
238 throws SecurityException {
Dianne Hackborn254cb442010-01-27 19:23:59 -0800239 final int callingUid = Binder.getCallingUid();
240 if (who != null) {
241 ActiveAdmin admin = mAdminMap.get(who);
242 if (admin == null) {
243 throw new SecurityException("No active admin " + who);
244 }
245 if (admin.getUid() != callingUid) {
246 throw new SecurityException("Admin " + who + " is not owned by uid "
247 + Binder.getCallingUid());
248 }
249 if (!admin.info.usesPolicy(reqPolicy)) {
250 throw new SecurityException("Admin " + admin.info.getComponent()
251 + " did not specify uses-policy for: "
252 + admin.info.getTagForPolicy(reqPolicy));
253 }
254 return admin;
255 } else {
256 final int N = mAdminList.size();
257 for (int i=0; i<N; i++) {
258 ActiveAdmin admin = mAdminList.get(i);
259 if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) {
260 return admin;
261 }
262 }
263 throw new SecurityException("No active admin owned by uid "
264 + Binder.getCallingUid() + " for policy #" + reqPolicy);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800265 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800266 }
267
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800268 void sendAdminCommandLocked(ActiveAdmin admin, String action) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800269 Intent intent = new Intent(action);
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800270 intent.setComponent(admin.info.getComponent());
Dianne Hackbornd6847842010-01-12 18:14:19 -0800271 mContext.sendBroadcast(intent);
272 }
273
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800274 void sendAdminCommandLocked(String action, int reqPolicy) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800275 final int N = mAdminList.size();
276 if (N > 0) {
277 for (int i=0; i<N; i++) {
278 ActiveAdmin admin = mAdminList.get(i);
279 if (admin.info.usesPolicy(reqPolicy)) {
280 sendAdminCommandLocked(admin, action);
281 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800282 }
Dianne Hackborn4141d032010-01-21 16:29:00 -0800283 }
284 }
285
Dianne Hackbornd6847842010-01-12 18:14:19 -0800286 void removeActiveAdminLocked(ComponentName adminReceiver) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800287 ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
288 if (admin != null) {
289 sendAdminCommandLocked(admin,
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800290 DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800291 // XXX need to wait for it to complete.
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800292 mAdminList.remove(admin);
293 mAdminMap.remove(adminReceiver);
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800294 validatePasswordOwnerLocked();
Dianne Hackbornd6847842010-01-12 18:14:19 -0800295 }
296 }
297
298 public DeviceAdminInfo findAdmin(ComponentName adminName) {
299 Intent resolveIntent = new Intent();
300 resolveIntent.setComponent(adminName);
301 List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceivers(
302 resolveIntent, PackageManager.GET_META_DATA);
303 if (infos == null || infos.size() <= 0) {
304 throw new IllegalArgumentException("Unknown admin: " + adminName);
305 }
306
307 try {
308 return new DeviceAdminInfo(mContext, infos.get(0));
309 } catch (XmlPullParserException e) {
310 Log.w(TAG, "Bad device admin requested: " + adminName, e);
311 return null;
312 } catch (IOException e) {
313 Log.w(TAG, "Bad device admin requested: " + adminName, e);
314 return null;
315 }
316 }
317
318 private static JournaledFile makeJournaledFile() {
319 final String base = "/data/system/device_policies.xml";
320 return new JournaledFile(new File(base), new File(base + ".tmp"));
321 }
322
323 private void saveSettingsLocked() {
324 JournaledFile journal = makeJournaledFile();
325 FileOutputStream stream = null;
326 try {
327 stream = new FileOutputStream(journal.chooseForWrite(), false);
328 XmlSerializer out = new FastXmlSerializer();
329 out.setOutput(stream, "utf-8");
330 out.startDocument(null, true);
331
332 out.startTag(null, "policies");
333
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800334 final int N = mAdminList.size();
335 for (int i=0; i<N; i++) {
336 ActiveAdmin ap = mAdminList.get(i);
337 if (ap != null) {
338 out.startTag(null, "admin");
339 out.attribute(null, "name", ap.info.getComponent().flattenToString());
340 ap.writeToXml(out);
341 out.endTag(null, "admin");
342 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800343 }
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800344
Dianne Hackbornd6847842010-01-12 18:14:19 -0800345 out.endTag(null, "policies");
346
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800347 if (mPasswordOwner >= 0) {
348 out.startTag(null, "password-owner");
349 out.attribute(null, "value", Integer.toString(mPasswordOwner));
350 out.endTag(null, "password-owner");
351 }
352
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800353 if (mFailedPasswordAttempts != 0) {
354 out.startTag(null, "failed-password-attempts");
355 out.attribute(null, "value", Integer.toString(mFailedPasswordAttempts));
356 out.endTag(null, "failed-password-attempts");
357 }
358
Dianne Hackbornd6847842010-01-12 18:14:19 -0800359 out.endDocument();
360 stream.close();
361 journal.commit();
362 } catch (IOException e) {
363 try {
364 if (stream != null) {
365 stream.close();
366 }
367 } catch (IOException ex) {
368 // Ignore
369 }
370 journal.rollback();
371 }
372 }
373
374 private void loadSettingsLocked() {
375 JournaledFile journal = makeJournaledFile();
376 FileInputStream stream = null;
377 File file = journal.chooseForRead();
Dianne Hackbornd6847842010-01-12 18:14:19 -0800378 try {
379 stream = new FileInputStream(file);
380 XmlPullParser parser = Xml.newPullParser();
381 parser.setInput(stream, null);
382
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800383 int type;
384 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
385 && type != XmlPullParser.START_TAG) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800386 }
387 String tag = parser.getName();
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800388 if (!"policies".equals(tag)) {
389 throw new XmlPullParserException(
390 "Settings do not start with policies tag: found " + tag);
391 }
392 type = parser.next();
393 int outerDepth = parser.getDepth();
394 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
395 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
396 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
397 continue;
398 }
399 tag = parser.getName();
400 if ("admin".equals(tag)) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800401 String name = parser.getAttributeValue(null, "name");
402 try {
403 DeviceAdminInfo dai = findAdmin(
404 ComponentName.unflattenFromString(name));
405 if (dai != null) {
406 ActiveAdmin ap = new ActiveAdmin(dai);
407 ap.readFromXml(parser);
408 mAdminMap.put(ap.info.getComponent(), ap);
409 mAdminList.add(ap);
410 }
411 } catch (RuntimeException e) {
412 Log.w(TAG, "Failed loading admin " + name, e);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800413 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800414 } else if ("failed-password-attempts".equals(tag)) {
415 mFailedPasswordAttempts = Integer.parseInt(
416 parser.getAttributeValue(null, "value"));
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800417 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800418 } else if ("password-owner".equals(tag)) {
419 mPasswordOwner = Integer.parseInt(
420 parser.getAttributeValue(null, "value"));
421 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800422 } else {
423 Log.w(TAG, "Unknown tag: " + tag);
424 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800425 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800426 }
427 } catch (NullPointerException e) {
428 Log.w(TAG, "failed parsing " + file + " " + e);
429 } catch (NumberFormatException e) {
430 Log.w(TAG, "failed parsing " + file + " " + e);
431 } catch (XmlPullParserException e) {
432 Log.w(TAG, "failed parsing " + file + " " + e);
433 } catch (IOException e) {
434 Log.w(TAG, "failed parsing " + file + " " + e);
435 } catch (IndexOutOfBoundsException e) {
436 Log.w(TAG, "failed parsing " + file + " " + e);
437 }
438 try {
439 if (stream != null) {
440 stream.close();
441 }
442 } catch (IOException e) {
443 // Ignore
444 }
445
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800446 validatePasswordOwnerLocked();
447
Dianne Hackborn254cb442010-01-27 19:23:59 -0800448 long timeMs = getMaximumTimeToLock(null);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800449 if (timeMs <= 0) {
450 timeMs = Integer.MAX_VALUE;
451 }
452 try {
453 getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
454 } catch (RemoteException e) {
455 Log.w(TAG, "Failure talking with power manager", e);
456 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800457 }
458
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800459 void validatePasswordOwnerLocked() {
460 if (mPasswordOwner >= 0) {
461 boolean haveOwner = false;
462 for (int i=mAdminList.size()-1; i>=0; i--) {
463 if (mAdminList.get(i).getUid() == mPasswordOwner) {
464 haveOwner = true;
465 break;
466 }
467 }
468 if (!haveOwner) {
469 Log.w(TAG, "Previous password owner " + mPasswordOwner
470 + " no longer active; disabling");
471 mPasswordOwner = -1;
472 }
473 }
474 }
475
Dianne Hackbornd6847842010-01-12 18:14:19 -0800476 public void systemReady() {
477 synchronized (this) {
478 loadSettingsLocked();
479 }
480 }
481
482 public void setActiveAdmin(ComponentName adminReceiver) {
483 mContext.enforceCallingOrSelfPermission(
484 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
485
486 DeviceAdminInfo info = findAdmin(adminReceiver);
487 if (info == null) {
488 throw new IllegalArgumentException("Bad admin: " + adminReceiver);
489 }
490 synchronized (this) {
491 long ident = Binder.clearCallingIdentity();
492 try {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800493 if (getActiveAdminUncheckedLocked(adminReceiver) != null) {
494 throw new IllegalArgumentException("Admin is already added");
Dianne Hackbornd6847842010-01-12 18:14:19 -0800495 }
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800496 ActiveAdmin admin = new ActiveAdmin(info);
497 mAdminMap.put(adminReceiver, admin);
498 mAdminList.add(admin);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800499 saveSettingsLocked();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800500 sendAdminCommandLocked(admin,
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800501 DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800502 } finally {
503 Binder.restoreCallingIdentity(ident);
504 }
505 }
506 }
507
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800508 public boolean isAdminActive(ComponentName adminReceiver) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800509 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800510 return getActiveAdminUncheckedLocked(adminReceiver) != null;
511 }
512 }
513
514 public List<ComponentName> getActiveAdmins() {
515 synchronized (this) {
516 final int N = mAdminList.size();
517 if (N <= 0) {
518 return null;
519 }
520 ArrayList<ComponentName> res = new ArrayList<ComponentName>(N);
521 for (int i=0; i<N; i++) {
522 res.add(mAdminList.get(i).info.getComponent());
523 }
524 return res;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800525 }
526 }
527
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800528 public boolean packageHasActiveAdmins(String packageName) {
529 synchronized (this) {
530 final int N = mAdminList.size();
531 for (int i=0; i<N; i++) {
532 if (mAdminList.get(i).info.getPackageName().equals(packageName)) {
533 return true;
534 }
535 }
536 return false;
537 }
538 }
539
Dianne Hackbornd6847842010-01-12 18:14:19 -0800540 public void removeActiveAdmin(ComponentName adminReceiver) {
541 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800542 ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
543 if (admin == null) {
544 return;
545 }
546 if (admin.getUid() != Binder.getCallingUid()) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800547 mContext.enforceCallingOrSelfPermission(
548 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
549 }
550 long ident = Binder.clearCallingIdentity();
551 try {
552 removeActiveAdminLocked(adminReceiver);
553 } finally {
554 Binder.restoreCallingIdentity(ident);
555 }
556 }
557 }
558
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800559 public void setPasswordQuality(ComponentName who, int mode) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800560 synchronized (this) {
561 if (who == null) {
562 throw new NullPointerException("ComponentName is null");
563 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800564 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
565 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800566 if (ap.passwordQuality != mode) {
567 ap.passwordQuality = mode;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800568 saveSettingsLocked();
569 }
570 }
571 }
572
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800573 public int getPasswordQuality(ComponentName who) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800574 synchronized (this) {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800575 int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
Dianne Hackborn254cb442010-01-27 19:23:59 -0800576
577 if (who != null) {
578 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800579 return admin != null ? admin.passwordQuality : mode;
Dianne Hackborn254cb442010-01-27 19:23:59 -0800580 }
581
582 final int N = mAdminList.size();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800583 for (int i=0; i<N; i++) {
584 ActiveAdmin admin = mAdminList.get(i);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800585 if (mode < admin.passwordQuality) {
586 mode = admin.passwordQuality;
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800587 }
588 }
589 return mode;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800590 }
591 }
592
Dianne Hackborn254cb442010-01-27 19:23:59 -0800593 public void setPasswordMinimumLength(ComponentName who, int length) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800594 synchronized (this) {
595 if (who == null) {
596 throw new NullPointerException("ComponentName is null");
597 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800598 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
599 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800600 if (ap.minimumPasswordLength != length) {
601 ap.minimumPasswordLength = length;
602 saveSettingsLocked();
603 }
604 }
605 }
606
Dianne Hackborn254cb442010-01-27 19:23:59 -0800607 public int getPasswordMinimumLength(ComponentName who) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800608 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800609 int length = 0;
Dianne Hackborn254cb442010-01-27 19:23:59 -0800610
611 if (who != null) {
612 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
613 return admin != null ? admin.minimumPasswordLength : length;
614 }
615
616 final int N = mAdminList.size();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800617 for (int i=0; i<N; i++) {
618 ActiveAdmin admin = mAdminList.get(i);
619 if (length < admin.minimumPasswordLength) {
620 length = admin.minimumPasswordLength;
621 }
622 }
623 return length;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800624 }
625 }
626
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800627 public boolean isActivePasswordSufficient() {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800628 synchronized (this) {
629 // This API can only be called by an active device admin,
630 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800631 getActiveAdminForCallerLocked(null,
632 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800633 return mActivePasswordQuality >= getPasswordQuality(null)
Dianne Hackborn254cb442010-01-27 19:23:59 -0800634 && mActivePasswordLength >= getPasswordMinimumLength(null);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800635 }
636 }
637
638 public int getCurrentFailedPasswordAttempts() {
639 synchronized (this) {
640 // This API can only be called by an active device admin,
641 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800642 getActiveAdminForCallerLocked(null,
643 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800644 return mFailedPasswordAttempts;
645 }
646 }
647
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800648 public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) {
649 synchronized (this) {
650 // This API can only be called by an active device admin,
651 // so try to retrieve it to check that the caller is one.
652 getActiveAdminForCallerLocked(who,
653 DeviceAdminInfo.USES_POLICY_WIPE_DATA);
654 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
655 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
656 if (ap.maximumFailedPasswordsForWipe != num) {
657 ap.maximumFailedPasswordsForWipe = num;
658 saveSettingsLocked();
659 }
660 }
661 }
662
Dianne Hackborn254cb442010-01-27 19:23:59 -0800663 public int getMaximumFailedPasswordsForWipe(ComponentName who) {
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800664 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800665 int count = 0;
Dianne Hackborn254cb442010-01-27 19:23:59 -0800666
667 if (who != null) {
668 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
669 return admin != null ? admin.maximumFailedPasswordsForWipe : count;
670 }
671
672 final int N = mAdminList.size();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800673 for (int i=0; i<N; i++) {
674 ActiveAdmin admin = mAdminList.get(i);
675 if (count == 0) {
676 count = admin.maximumFailedPasswordsForWipe;
677 } else if (admin.maximumFailedPasswordsForWipe != 0
678 && count > admin.maximumFailedPasswordsForWipe) {
679 count = admin.maximumFailedPasswordsForWipe;
680 }
681 }
682 return count;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800683 }
684 }
685
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800686 public boolean resetPassword(String password, int flags) {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800687 int quality;
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800688 synchronized (this) {
689 // This API can only be called by an active device admin,
690 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800691 getActiveAdminForCallerLocked(null,
692 DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800693 quality = getPasswordQuality(null);
694 if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
695 int adjQuality = LockPatternUtils.adjustPasswordMode(password, quality);
696 if (adjQuality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
697 Log.w(TAG, "resetPassword: password does not meet quality " + quality);
698 return false;
699 }
700 quality = adjQuality;
701 }
702 int length = getPasswordMinimumLength(null);
703 if (password.length() < length) {
704 Log.w(TAG, "resetPassword: password does not meet length " + length);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800705 return false;
706 }
707 }
708
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800709 int callingUid = Binder.getCallingUid();
710 if (mPasswordOwner >= 0 && mPasswordOwner != callingUid) {
711 Log.w(TAG, "resetPassword: already set by another uid and not entered by user");
712 return false;
713 }
714
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800715 // Don't do this with the lock held, because it is going to call
716 // back in to the service.
717 long ident = Binder.clearCallingIdentity();
718 try {
719 LockPatternUtils utils = new LockPatternUtils(mContext);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800720 utils.saveLockPassword(password, quality);
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800721 int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY)
722 != 0 ? callingUid : -1;
723 if (mPasswordOwner != newOwner) {
724 mPasswordOwner = newOwner;
725 saveSettingsLocked();
726 }
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800727 } finally {
728 Binder.restoreCallingIdentity(ident);
729 }
730
731 return true;
732 }
733
Dianne Hackbornd6847842010-01-12 18:14:19 -0800734 public void setMaximumTimeToLock(ComponentName who, long timeMs) {
735 synchronized (this) {
736 if (who == null) {
737 throw new NullPointerException("ComponentName is null");
738 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800739 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
Dianne Hackborn315ada72010-02-11 12:14:08 -0800740 DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800741 if (ap.maximumTimeToUnlock != timeMs) {
742 ap.maximumTimeToUnlock = timeMs;
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800743
744 long ident = Binder.clearCallingIdentity();
745 try {
746 saveSettingsLocked();
Dianne Hackborn254cb442010-01-27 19:23:59 -0800747
748 timeMs = getMaximumTimeToLock(null);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800749 if (timeMs <= 0) {
750 timeMs = Integer.MAX_VALUE;
751 }
Dianne Hackborn254cb442010-01-27 19:23:59 -0800752
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800753 try {
754 getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
755 } catch (RemoteException e) {
756 Log.w(TAG, "Failure talking with power manager", e);
757 }
758 } finally {
759 Binder.restoreCallingIdentity(ident);
760 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800761 }
762 }
763 }
764
Dianne Hackborn254cb442010-01-27 19:23:59 -0800765 public long getMaximumTimeToLock(ComponentName who) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800766 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800767 long time = 0;
Dianne Hackborn254cb442010-01-27 19:23:59 -0800768
769 if (who != null) {
770 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
771 return admin != null ? admin.maximumTimeToUnlock : time;
772 }
773
774 final int N = mAdminList.size();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800775 for (int i=0; i<N; i++) {
776 ActiveAdmin admin = mAdminList.get(i);
777 if (time == 0) {
778 time = admin.maximumTimeToUnlock;
779 } else if (admin.maximumTimeToUnlock != 0
780 && time > admin.maximumTimeToUnlock) {
781 time = admin.maximumTimeToUnlock;
782 }
783 }
784 return time;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800785 }
786 }
787
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800788 public void lockNow() {
789 synchronized (this) {
790 // This API can only be called by an active device admin,
791 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800792 getActiveAdminForCallerLocked(null,
793 DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
Dianne Hackborn254cb442010-01-27 19:23:59 -0800794 long ident = Binder.clearCallingIdentity();
795 try {
796 mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(),
797 WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN);
798 } catch (RemoteException e) {
799 } finally {
800 Binder.restoreCallingIdentity(ident);
801 }
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800802 }
803 }
804
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800805 void wipeDataLocked(int flags) {
806 try {
807 RecoverySystem.rebootWipeUserData(mContext);
808 } catch (IOException e) {
809 Log.w(TAG, "Failed requesting data wipe", e);
810 }
811 }
812
Dianne Hackbornd6847842010-01-12 18:14:19 -0800813 public void wipeData(int flags) {
814 synchronized (this) {
815 // This API can only be called by an active device admin,
816 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800817 getActiveAdminForCallerLocked(null,
818 DeviceAdminInfo.USES_POLICY_WIPE_DATA);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800819 long ident = Binder.clearCallingIdentity();
820 try {
821 wipeDataLocked(flags);
822 } finally {
823 Binder.restoreCallingIdentity(ident);
824 }
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800825 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800826 }
827
828 public void getRemoveWarning(ComponentName comp, final RemoteCallback result) {
829 mContext.enforceCallingOrSelfPermission(
830 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
831
832 synchronized (this) {
833 ActiveAdmin admin = getActiveAdminUncheckedLocked(comp);
834 if (admin == null) {
835 try {
836 result.sendResult(null);
837 } catch (RemoteException e) {
838 }
839 return;
840 }
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800841 Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800842 intent.setComponent(admin.info.getComponent());
843 mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
844 @Override
845 public void onReceive(Context context, Intent intent) {
846 try {
847 result.sendResult(getResultExtras(false));
848 } catch (RemoteException e) {
849 }
850 }
851 }, null, Activity.RESULT_OK, null, null);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800852 }
853 }
854
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800855 public void setActivePasswordState(int quality, int length) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800856 mContext.enforceCallingOrSelfPermission(
857 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
858
859 synchronized (this) {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800860 if (mActivePasswordQuality != quality || mActivePasswordLength != length
Dianne Hackbornd6847842010-01-12 18:14:19 -0800861 || mFailedPasswordAttempts != 0) {
862 long ident = Binder.clearCallingIdentity();
863 try {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800864 mActivePasswordQuality = quality;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800865 mActivePasswordLength = length;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800866 if (mFailedPasswordAttempts != 0) {
867 mFailedPasswordAttempts = 0;
868 saveSettingsLocked();
869 }
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800870 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800871 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800872 } finally {
873 Binder.restoreCallingIdentity(ident);
874 }
875 }
876 }
877 }
878
879 public void reportFailedPasswordAttempt() {
880 mContext.enforceCallingOrSelfPermission(
881 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
882
883 synchronized (this) {
884 long ident = Binder.clearCallingIdentity();
885 try {
886 mFailedPasswordAttempts++;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800887 saveSettingsLocked();
Dianne Hackborn254cb442010-01-27 19:23:59 -0800888 int max = getMaximumFailedPasswordsForWipe(null);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800889 if (max > 0 && mFailedPasswordAttempts >= max) {
890 wipeDataLocked(0);
891 }
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800892 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800893 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800894 } finally {
895 Binder.restoreCallingIdentity(ident);
896 }
897 }
898 }
899
900 public void reportSuccessfulPasswordAttempt() {
901 mContext.enforceCallingOrSelfPermission(
902 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
903
904 synchronized (this) {
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800905 if (mFailedPasswordAttempts != 0 || mPasswordOwner >= 0) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800906 long ident = Binder.clearCallingIdentity();
907 try {
908 mFailedPasswordAttempts = 0;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800909 mPasswordOwner = -1;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800910 saveSettingsLocked();
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800911 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800912 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800913 } finally {
914 Binder.restoreCallingIdentity(ident);
915 }
916 }
917 }
918 }
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800919
920 @Override
921 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
922 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
923 != PackageManager.PERMISSION_GRANTED) {
924
925 pw.println("Permission Denial: can't dump DevicePolicyManagerService from from pid="
926 + Binder.getCallingPid()
927 + ", uid=" + Binder.getCallingUid());
928 return;
929 }
930
931 final Printer p = new PrintWriterPrinter(pw);
932
933 synchronized (this) {
934 p.println("Current Device Policy Manager state:");
935
936 p.println(" Enabled Device Admins:");
937 final int N = mAdminList.size();
938 for (int i=0; i<N; i++) {
939 ActiveAdmin ap = mAdminList.get(i);
940 if (ap != null) {
941 pw.print(" "); pw.print(ap.info.getComponent().flattenToShortString());
942 pw.println(":");
943 ap.dump(" ", pw);
944 }
945 }
946
947 pw.println(" ");
948 pw.print(" mActivePasswordQuality="); pw.println(mActivePasswordQuality);
949 pw.print(" mActivePasswordLength="); pw.println(mActivePasswordLength);
950 pw.print(" mFailedPasswordAttempts="); pw.println(mFailedPasswordAttempts);
951 pw.print(" mPasswordOwner="); pw.println(mPasswordOwner);
952 }
953 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800954}