blob: 7fb7db09637f671737dcd9077bbc976e971a266f [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 Hackborn85f2c9c2010-03-22 11:12:48 -070049import android.util.Slog;
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 {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700153 Slog.w(TAG, "Unknown admin tag: " + tag);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800154 }
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 }
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700168 pw.print(prefix); pw.print("passwordQuality=0x");
169 pw.print(Integer.toHexString(passwordQuality));
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800170 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) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700188 Slog.w(TAG, "Admin unexpectedly uninstalled: "
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800189 + 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) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700197 Slog.w(TAG, "Admin package change removed component: "
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800198 + 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) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700311 Slog.w(TAG, "Bad device admin requested: " + adminName, e);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800312 return null;
313 } catch (IOException e) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700314 Slog.w(TAG, "Bad device admin requested: " + adminName, e);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800315 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 Hackborn87bba1e2010-02-26 17:25:54 -0800346 if (mPasswordOwner >= 0) {
347 out.startTag(null, "password-owner");
348 out.attribute(null, "value", Integer.toString(mPasswordOwner));
349 out.endTag(null, "password-owner");
350 }
351
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800352 if (mFailedPasswordAttempts != 0) {
353 out.startTag(null, "failed-password-attempts");
354 out.attribute(null, "value", Integer.toString(mFailedPasswordAttempts));
355 out.endTag(null, "failed-password-attempts");
356 }
357
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700358 if (mActivePasswordQuality != 0 || mActivePasswordLength != 0) {
359 out.startTag(null, "active-password");
360 out.attribute(null, "quality", Integer.toString(mActivePasswordQuality));
361 out.attribute(null, "length", Integer.toString(mActivePasswordLength));
362 out.endTag(null, "active-password");
363 }
364
365 out.endTag(null, "policies");
366
Dianne Hackbornd6847842010-01-12 18:14:19 -0800367 out.endDocument();
368 stream.close();
369 journal.commit();
370 } catch (IOException e) {
371 try {
372 if (stream != null) {
373 stream.close();
374 }
375 } catch (IOException ex) {
376 // Ignore
377 }
378 journal.rollback();
379 }
380 }
381
382 private void loadSettingsLocked() {
383 JournaledFile journal = makeJournaledFile();
384 FileInputStream stream = null;
385 File file = journal.chooseForRead();
Dianne Hackbornd6847842010-01-12 18:14:19 -0800386 try {
387 stream = new FileInputStream(file);
388 XmlPullParser parser = Xml.newPullParser();
389 parser.setInput(stream, null);
390
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800391 int type;
392 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
393 && type != XmlPullParser.START_TAG) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800394 }
395 String tag = parser.getName();
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800396 if (!"policies".equals(tag)) {
397 throw new XmlPullParserException(
398 "Settings do not start with policies tag: found " + tag);
399 }
400 type = parser.next();
401 int outerDepth = parser.getDepth();
402 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
403 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
404 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
405 continue;
406 }
407 tag = parser.getName();
408 if ("admin".equals(tag)) {
Dianne Hackborne83cefce2010-02-04 17:38:14 -0800409 String name = parser.getAttributeValue(null, "name");
410 try {
411 DeviceAdminInfo dai = findAdmin(
412 ComponentName.unflattenFromString(name));
413 if (dai != null) {
414 ActiveAdmin ap = new ActiveAdmin(dai);
415 ap.readFromXml(parser);
416 mAdminMap.put(ap.info.getComponent(), ap);
417 mAdminList.add(ap);
418 }
419 } catch (RuntimeException e) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700420 Slog.w(TAG, "Failed loading admin " + name, e);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800421 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800422 } else if ("failed-password-attempts".equals(tag)) {
423 mFailedPasswordAttempts = Integer.parseInt(
424 parser.getAttributeValue(null, "value"));
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800425 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800426 } else if ("password-owner".equals(tag)) {
427 mPasswordOwner = Integer.parseInt(
428 parser.getAttributeValue(null, "value"));
429 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700430 } else if ("active-password".equals(tag)) {
431 mActivePasswordQuality = Integer.parseInt(
432 parser.getAttributeValue(null, "quality"));
433 mActivePasswordLength = Integer.parseInt(
434 parser.getAttributeValue(null, "length"));
435 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800436 } else {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700437 Slog.w(TAG, "Unknown tag: " + tag);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800438 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800439 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800440 }
441 } catch (NullPointerException e) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700442 Slog.w(TAG, "failed parsing " + file + " " + e);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800443 } catch (NumberFormatException e) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700444 Slog.w(TAG, "failed parsing " + file + " " + e);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800445 } catch (XmlPullParserException e) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700446 Slog.w(TAG, "failed parsing " + file + " " + e);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800447 } catch (IOException e) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700448 Slog.w(TAG, "failed parsing " + file + " " + e);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800449 } catch (IndexOutOfBoundsException e) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700450 Slog.w(TAG, "failed parsing " + file + " " + e);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800451 }
452 try {
453 if (stream != null) {
454 stream.close();
455 }
456 } catch (IOException e) {
457 // Ignore
458 }
459
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700460 // Validate that what we stored for the password quality matches
461 // sufficiently what is currently set. Note that this is only
462 // a sanity check in case the two get out of sync; this should
463 // never normally happen.
464 LockPatternUtils utils = new LockPatternUtils(mContext);
465 if (utils.getActivePasswordQuality() < mActivePasswordQuality) {
466 Slog.w(TAG, "Active password quality 0x"
467 + Integer.toHexString(mActivePasswordQuality)
468 + " does not match actual quality 0x"
469 + Integer.toHexString(utils.getActivePasswordQuality()));
470 mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
471 mActivePasswordLength = 0;
472 }
473
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800474 validatePasswordOwnerLocked();
475
Dianne Hackborn254cb442010-01-27 19:23:59 -0800476 long timeMs = getMaximumTimeToLock(null);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800477 if (timeMs <= 0) {
478 timeMs = Integer.MAX_VALUE;
479 }
480 try {
481 getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
482 } catch (RemoteException e) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700483 Slog.w(TAG, "Failure talking with power manager", e);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800484 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800485 }
486
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700487 static void validateQualityConstant(int quality) {
488 switch (quality) {
489 case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
490 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
491 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
492 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
493 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
494 return;
495 }
496 throw new IllegalArgumentException("Invalid quality constant: 0x"
497 + Integer.toHexString(quality));
498 }
499
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800500 void validatePasswordOwnerLocked() {
501 if (mPasswordOwner >= 0) {
502 boolean haveOwner = false;
503 for (int i=mAdminList.size()-1; i>=0; i--) {
504 if (mAdminList.get(i).getUid() == mPasswordOwner) {
505 haveOwner = true;
506 break;
507 }
508 }
509 if (!haveOwner) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700510 Slog.w(TAG, "Previous password owner " + mPasswordOwner
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800511 + " no longer active; disabling");
512 mPasswordOwner = -1;
513 }
514 }
515 }
516
Dianne Hackbornd6847842010-01-12 18:14:19 -0800517 public void systemReady() {
518 synchronized (this) {
519 loadSettingsLocked();
520 }
521 }
522
523 public void setActiveAdmin(ComponentName adminReceiver) {
524 mContext.enforceCallingOrSelfPermission(
525 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
526
527 DeviceAdminInfo info = findAdmin(adminReceiver);
528 if (info == null) {
529 throw new IllegalArgumentException("Bad admin: " + adminReceiver);
530 }
531 synchronized (this) {
532 long ident = Binder.clearCallingIdentity();
533 try {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800534 if (getActiveAdminUncheckedLocked(adminReceiver) != null) {
535 throw new IllegalArgumentException("Admin is already added");
Dianne Hackbornd6847842010-01-12 18:14:19 -0800536 }
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800537 ActiveAdmin admin = new ActiveAdmin(info);
538 mAdminMap.put(adminReceiver, admin);
539 mAdminList.add(admin);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800540 saveSettingsLocked();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800541 sendAdminCommandLocked(admin,
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800542 DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800543 } finally {
544 Binder.restoreCallingIdentity(ident);
545 }
546 }
547 }
548
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800549 public boolean isAdminActive(ComponentName adminReceiver) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800550 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800551 return getActiveAdminUncheckedLocked(adminReceiver) != null;
552 }
553 }
554
555 public List<ComponentName> getActiveAdmins() {
556 synchronized (this) {
557 final int N = mAdminList.size();
558 if (N <= 0) {
559 return null;
560 }
561 ArrayList<ComponentName> res = new ArrayList<ComponentName>(N);
562 for (int i=0; i<N; i++) {
563 res.add(mAdminList.get(i).info.getComponent());
564 }
565 return res;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800566 }
567 }
568
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800569 public boolean packageHasActiveAdmins(String packageName) {
570 synchronized (this) {
571 final int N = mAdminList.size();
572 for (int i=0; i<N; i++) {
573 if (mAdminList.get(i).info.getPackageName().equals(packageName)) {
574 return true;
575 }
576 }
577 return false;
578 }
579 }
580
Dianne Hackbornd6847842010-01-12 18:14:19 -0800581 public void removeActiveAdmin(ComponentName adminReceiver) {
582 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800583 ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver);
584 if (admin == null) {
585 return;
586 }
587 if (admin.getUid() != Binder.getCallingUid()) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800588 mContext.enforceCallingOrSelfPermission(
589 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
590 }
591 long ident = Binder.clearCallingIdentity();
592 try {
593 removeActiveAdminLocked(adminReceiver);
594 } finally {
595 Binder.restoreCallingIdentity(ident);
596 }
597 }
598 }
599
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700600 public void setPasswordQuality(ComponentName who, int quality) {
601 validateQualityConstant(quality);
602
Dianne Hackbornd6847842010-01-12 18:14:19 -0800603 synchronized (this) {
604 if (who == null) {
605 throw new NullPointerException("ComponentName is null");
606 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800607 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
608 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700609 if (ap.passwordQuality != quality) {
610 ap.passwordQuality = quality;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800611 saveSettingsLocked();
612 }
613 }
614 }
615
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800616 public int getPasswordQuality(ComponentName who) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800617 synchronized (this) {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800618 int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
Dianne Hackborn254cb442010-01-27 19:23:59 -0800619
620 if (who != null) {
621 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800622 return admin != null ? admin.passwordQuality : mode;
Dianne Hackborn254cb442010-01-27 19:23:59 -0800623 }
624
625 final int N = mAdminList.size();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800626 for (int i=0; i<N; i++) {
627 ActiveAdmin admin = mAdminList.get(i);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800628 if (mode < admin.passwordQuality) {
629 mode = admin.passwordQuality;
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800630 }
631 }
632 return mode;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800633 }
634 }
635
Dianne Hackborn254cb442010-01-27 19:23:59 -0800636 public void setPasswordMinimumLength(ComponentName who, int length) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800637 synchronized (this) {
638 if (who == null) {
639 throw new NullPointerException("ComponentName is null");
640 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800641 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
642 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800643 if (ap.minimumPasswordLength != length) {
644 ap.minimumPasswordLength = length;
645 saveSettingsLocked();
646 }
647 }
648 }
649
Dianne Hackborn254cb442010-01-27 19:23:59 -0800650 public int getPasswordMinimumLength(ComponentName who) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800651 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800652 int length = 0;
Dianne Hackborn254cb442010-01-27 19:23:59 -0800653
654 if (who != null) {
655 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
656 return admin != null ? admin.minimumPasswordLength : length;
657 }
658
659 final int N = mAdminList.size();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800660 for (int i=0; i<N; i++) {
661 ActiveAdmin admin = mAdminList.get(i);
662 if (length < admin.minimumPasswordLength) {
663 length = admin.minimumPasswordLength;
664 }
665 }
666 return length;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800667 }
668 }
669
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800670 public boolean isActivePasswordSufficient() {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800671 synchronized (this) {
672 // This API can only be called by an active device admin,
673 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800674 getActiveAdminForCallerLocked(null,
675 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800676 return mActivePasswordQuality >= getPasswordQuality(null)
Dianne Hackborn254cb442010-01-27 19:23:59 -0800677 && mActivePasswordLength >= getPasswordMinimumLength(null);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800678 }
679 }
680
681 public int getCurrentFailedPasswordAttempts() {
682 synchronized (this) {
683 // This API can only be called by an active device admin,
684 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800685 getActiveAdminForCallerLocked(null,
686 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800687 return mFailedPasswordAttempts;
688 }
689 }
690
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800691 public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) {
692 synchronized (this) {
693 // This API can only be called by an active device admin,
694 // so try to retrieve it to check that the caller is one.
695 getActiveAdminForCallerLocked(who,
696 DeviceAdminInfo.USES_POLICY_WIPE_DATA);
697 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
698 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
699 if (ap.maximumFailedPasswordsForWipe != num) {
700 ap.maximumFailedPasswordsForWipe = num;
701 saveSettingsLocked();
702 }
703 }
704 }
705
Dianne Hackborn254cb442010-01-27 19:23:59 -0800706 public int getMaximumFailedPasswordsForWipe(ComponentName who) {
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800707 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800708 int count = 0;
Dianne Hackborn254cb442010-01-27 19:23:59 -0800709
710 if (who != null) {
711 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
712 return admin != null ? admin.maximumFailedPasswordsForWipe : count;
713 }
714
715 final int N = mAdminList.size();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800716 for (int i=0; i<N; i++) {
717 ActiveAdmin admin = mAdminList.get(i);
718 if (count == 0) {
719 count = admin.maximumFailedPasswordsForWipe;
720 } else if (admin.maximumFailedPasswordsForWipe != 0
721 && count > admin.maximumFailedPasswordsForWipe) {
722 count = admin.maximumFailedPasswordsForWipe;
723 }
724 }
725 return count;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800726 }
727 }
728
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800729 public boolean resetPassword(String password, int flags) {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800730 int quality;
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800731 synchronized (this) {
732 // This API can only be called by an active device admin,
733 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800734 getActiveAdminForCallerLocked(null,
735 DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800736 quality = getPasswordQuality(null);
737 if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700738 int realQuality = LockPatternUtils.computePasswordQuality(password);
739 if (realQuality < quality) {
740 Slog.w(TAG, "resetPassword: password quality 0x"
741 + Integer.toHexString(quality)
742 + " does not meet required quality 0x"
743 + Integer.toHexString(quality));
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800744 return false;
745 }
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700746 quality = realQuality;
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800747 }
748 int length = getPasswordMinimumLength(null);
749 if (password.length() < length) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700750 Slog.w(TAG, "resetPassword: password length " + password.length()
751 + " does not meet required length " + length);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800752 return false;
753 }
754 }
755
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800756 int callingUid = Binder.getCallingUid();
757 if (mPasswordOwner >= 0 && mPasswordOwner != callingUid) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700758 Slog.w(TAG, "resetPassword: already set by another uid and not entered by user");
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800759 return false;
760 }
761
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800762 // Don't do this with the lock held, because it is going to call
763 // back in to the service.
764 long ident = Binder.clearCallingIdentity();
765 try {
766 LockPatternUtils utils = new LockPatternUtils(mContext);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800767 utils.saveLockPassword(password, quality);
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700768 synchronized (this) {
769 int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY)
770 != 0 ? callingUid : -1;
771 if (mPasswordOwner != newOwner) {
772 mPasswordOwner = newOwner;
773 saveSettingsLocked();
774 }
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800775 }
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800776 } finally {
777 Binder.restoreCallingIdentity(ident);
778 }
779
780 return true;
781 }
782
Dianne Hackbornd6847842010-01-12 18:14:19 -0800783 public void setMaximumTimeToLock(ComponentName who, long timeMs) {
784 synchronized (this) {
785 if (who == null) {
786 throw new NullPointerException("ComponentName is null");
787 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800788 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
Dianne Hackborn315ada72010-02-11 12:14:08 -0800789 DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800790 if (ap.maximumTimeToUnlock != timeMs) {
791 ap.maximumTimeToUnlock = timeMs;
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800792
793 long ident = Binder.clearCallingIdentity();
794 try {
795 saveSettingsLocked();
Dianne Hackborn254cb442010-01-27 19:23:59 -0800796
797 timeMs = getMaximumTimeToLock(null);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800798 if (timeMs <= 0) {
799 timeMs = Integer.MAX_VALUE;
800 }
Dianne Hackborn254cb442010-01-27 19:23:59 -0800801
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800802 try {
803 getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
804 } catch (RemoteException e) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700805 Slog.w(TAG, "Failure talking with power manager", e);
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800806 }
807 } finally {
808 Binder.restoreCallingIdentity(ident);
809 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800810 }
811 }
812 }
813
Dianne Hackborn254cb442010-01-27 19:23:59 -0800814 public long getMaximumTimeToLock(ComponentName who) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800815 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800816 long time = 0;
Dianne Hackborn254cb442010-01-27 19:23:59 -0800817
818 if (who != null) {
819 ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
820 return admin != null ? admin.maximumTimeToUnlock : time;
821 }
822
823 final int N = mAdminList.size();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800824 for (int i=0; i<N; i++) {
825 ActiveAdmin admin = mAdminList.get(i);
826 if (time == 0) {
827 time = admin.maximumTimeToUnlock;
828 } else if (admin.maximumTimeToUnlock != 0
829 && time > admin.maximumTimeToUnlock) {
830 time = admin.maximumTimeToUnlock;
831 }
832 }
833 return time;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800834 }
835 }
836
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800837 public void lockNow() {
838 synchronized (this) {
839 // This API can only be called by an active device admin,
840 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800841 getActiveAdminForCallerLocked(null,
842 DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
Dianne Hackborn254cb442010-01-27 19:23:59 -0800843 long ident = Binder.clearCallingIdentity();
844 try {
845 mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(),
846 WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN);
847 } catch (RemoteException e) {
848 } finally {
849 Binder.restoreCallingIdentity(ident);
850 }
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800851 }
852 }
853
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800854 void wipeDataLocked(int flags) {
855 try {
856 RecoverySystem.rebootWipeUserData(mContext);
857 } catch (IOException e) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700858 Slog.w(TAG, "Failed requesting data wipe", e);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800859 }
860 }
861
Dianne Hackbornd6847842010-01-12 18:14:19 -0800862 public void wipeData(int flags) {
863 synchronized (this) {
864 // This API can only be called by an active device admin,
865 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800866 getActiveAdminForCallerLocked(null,
867 DeviceAdminInfo.USES_POLICY_WIPE_DATA);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800868 long ident = Binder.clearCallingIdentity();
869 try {
870 wipeDataLocked(flags);
871 } finally {
872 Binder.restoreCallingIdentity(ident);
873 }
Dianne Hackborndf83afa2010-01-20 13:37:26 -0800874 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800875 }
876
877 public void getRemoveWarning(ComponentName comp, final RemoteCallback result) {
878 mContext.enforceCallingOrSelfPermission(
879 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
880
881 synchronized (this) {
882 ActiveAdmin admin = getActiveAdminUncheckedLocked(comp);
883 if (admin == null) {
884 try {
885 result.sendResult(null);
886 } catch (RemoteException e) {
887 }
888 return;
889 }
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800890 Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800891 intent.setComponent(admin.info.getComponent());
892 mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
893 @Override
894 public void onReceive(Context context, Intent intent) {
895 try {
896 result.sendResult(getResultExtras(false));
897 } catch (RemoteException e) {
898 }
899 }
900 }, null, Activity.RESULT_OK, null, null);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800901 }
902 }
903
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800904 public void setActivePasswordState(int quality, int length) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800905 mContext.enforceCallingOrSelfPermission(
906 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
907
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700908 validateQualityConstant(quality);
909
Dianne Hackbornd6847842010-01-12 18:14:19 -0800910 synchronized (this) {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800911 if (mActivePasswordQuality != quality || mActivePasswordLength != length
Dianne Hackbornd6847842010-01-12 18:14:19 -0800912 || mFailedPasswordAttempts != 0) {
913 long ident = Binder.clearCallingIdentity();
914 try {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800915 mActivePasswordQuality = quality;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800916 mActivePasswordLength = length;
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700917 mFailedPasswordAttempts = 0;
918 saveSettingsLocked();
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800919 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800920 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800921 } finally {
922 Binder.restoreCallingIdentity(ident);
923 }
924 }
925 }
926 }
927
928 public void reportFailedPasswordAttempt() {
929 mContext.enforceCallingOrSelfPermission(
930 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
931
932 synchronized (this) {
933 long ident = Binder.clearCallingIdentity();
934 try {
935 mFailedPasswordAttempts++;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800936 saveSettingsLocked();
Dianne Hackborn254cb442010-01-27 19:23:59 -0800937 int max = getMaximumFailedPasswordsForWipe(null);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800938 if (max > 0 && mFailedPasswordAttempts >= max) {
939 wipeDataLocked(0);
940 }
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800941 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800942 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800943 } finally {
944 Binder.restoreCallingIdentity(ident);
945 }
946 }
947 }
948
949 public void reportSuccessfulPasswordAttempt() {
950 mContext.enforceCallingOrSelfPermission(
951 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
952
953 synchronized (this) {
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800954 if (mFailedPasswordAttempts != 0 || mPasswordOwner >= 0) {
Dianne Hackbornd6847842010-01-12 18:14:19 -0800955 long ident = Binder.clearCallingIdentity();
956 try {
957 mFailedPasswordAttempts = 0;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800958 mPasswordOwner = -1;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800959 saveSettingsLocked();
Dianne Hackbornef6b22f2010-02-16 20:38:49 -0800960 sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -0800961 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
Dianne Hackbornd6847842010-01-12 18:14:19 -0800962 } finally {
963 Binder.restoreCallingIdentity(ident);
964 }
965 }
966 }
967 }
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800968
969 @Override
970 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
971 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
972 != PackageManager.PERMISSION_GRANTED) {
973
974 pw.println("Permission Denial: can't dump DevicePolicyManagerService from from pid="
975 + Binder.getCallingPid()
976 + ", uid=" + Binder.getCallingUid());
977 return;
978 }
979
980 final Printer p = new PrintWriterPrinter(pw);
981
982 synchronized (this) {
983 p.println("Current Device Policy Manager state:");
984
985 p.println(" Enabled Device Admins:");
986 final int N = mAdminList.size();
987 for (int i=0; i<N; i++) {
988 ActiveAdmin ap = mAdminList.get(i);
989 if (ap != null) {
990 pw.print(" "); pw.print(ap.info.getComponent().flattenToShortString());
991 pw.println(":");
992 ap.dump(" ", pw);
993 }
994 }
995
996 pw.println(" ");
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700997 pw.print(" mActivePasswordQuality=0x");
998 pw.println(Integer.toHexString(mActivePasswordQuality));
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800999 pw.print(" mActivePasswordLength="); pw.println(mActivePasswordLength);
1000 pw.print(" mFailedPasswordAttempts="); pw.println(mFailedPasswordAttempts);
1001 pw.print(" mPasswordOwner="); pw.println(mPasswordOwner);
1002 }
1003 }
Dianne Hackbornd6847842010-01-12 18:14:19 -08001004}