2010-01-12 18:14:19 -08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2010 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package com.android.server;
|
|
|
|
|
2010-10-15 18:45:07 -07:00
|
|
|
import com.android.internal.os.storage.ExternalStorageFormatter;
|
2010-02-24 19:54:22 -08:00
|
|
|
import com.android.internal.util.FastXmlSerializer;
|
2010-03-18 22:47:17 -07:00
|
|
|
import com.android.internal.util.JournaledFile;
|
2010-02-24 19:54:22 -08:00
|
|
|
import com.android.internal.util.XmlUtils;
|
2010-01-20 13:37:26 -08:00
|
|
|
import com.android.internal.widget.LockPatternUtils;
|
2010-01-12 18:14:19 -08:00
|
|
|
|
|
|
|
import org.xmlpull.v1.XmlPullParser;
|
|
|
|
import org.xmlpull.v1.XmlPullParserException;
|
|
|
|
import org.xmlpull.v1.XmlSerializer;
|
|
|
|
|
2010-01-26 18:01:04 -08:00
|
|
|
import android.app.Activity;
|
2012-09-14 23:20:08 -07:00
|
|
|
import android.app.ActivityManagerNative;
|
2010-11-08 16:15:47 -08:00
|
|
|
import android.app.AlarmManager;
|
2012-09-14 23:20:08 -07:00
|
|
|
import android.app.AppGlobals;
|
2010-11-08 16:15:47 -08:00
|
|
|
import android.app.PendingIntent;
|
2010-02-26 17:25:54 -08:00
|
|
|
import android.app.admin.DeviceAdminInfo;
|
|
|
|
import android.app.admin.DeviceAdminReceiver;
|
|
|
|
import android.app.admin.DevicePolicyManager;
|
|
|
|
import android.app.admin.IDevicePolicyManager;
|
2010-01-26 18:01:04 -08:00
|
|
|
import android.content.BroadcastReceiver;
|
2010-01-12 18:14:19 -08:00
|
|
|
import android.content.ComponentName;
|
2010-08-03 10:51:06 -07:00
|
|
|
import android.content.ContentResolver;
|
2010-01-12 18:14:19 -08:00
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
2010-11-08 16:15:47 -08:00
|
|
|
import android.content.IntentFilter;
|
2012-09-14 23:20:08 -07:00
|
|
|
import android.content.pm.IPackageManager;
|
2010-01-12 18:14:19 -08:00
|
|
|
import android.content.pm.PackageManager;
|
2010-02-19 17:02:21 -08:00
|
|
|
import android.content.pm.PackageManager.NameNotFoundException;
|
2010-11-19 15:39:41 -08:00
|
|
|
import android.content.pm.ResolveInfo;
|
2010-01-12 18:14:19 -08:00
|
|
|
import android.os.Binder;
|
2011-10-17 17:30:21 -07:00
|
|
|
import android.os.Environment;
|
2010-11-08 16:15:47 -08:00
|
|
|
import android.os.Handler;
|
2010-01-20 13:37:26 -08:00
|
|
|
import android.os.IBinder;
|
|
|
|
import android.os.IPowerManager;
|
2010-10-15 18:45:07 -07:00
|
|
|
import android.os.PowerManager;
|
2012-09-14 23:20:08 -07:00
|
|
|
import android.os.Process;
|
2010-01-20 13:37:26 -08:00
|
|
|
import android.os.RecoverySystem;
|
2010-01-26 18:01:04 -08:00
|
|
|
import android.os.RemoteCallback;
|
2010-01-20 13:37:26 -08:00
|
|
|
import android.os.RemoteException;
|
|
|
|
import android.os.ServiceManager;
|
2010-01-27 19:23:59 -08:00
|
|
|
import android.os.SystemClock;
|
2011-01-20 16:35:09 -08:00
|
|
|
import android.os.SystemProperties;
|
2012-08-29 18:32:08 -07:00
|
|
|
import android.os.UserHandle;
|
2012-09-14 23:20:08 -07:00
|
|
|
import android.os.UserManager;
|
2010-08-03 10:51:06 -07:00
|
|
|
import android.provider.Settings;
|
2010-02-26 17:25:54 -08:00
|
|
|
import android.util.PrintWriterPrinter;
|
|
|
|
import android.util.Printer;
|
2010-11-19 15:39:41 -08:00
|
|
|
import android.util.Slog;
|
2012-09-14 23:20:08 -07:00
|
|
|
import android.util.SparseArray;
|
2010-01-12 18:14:19 -08:00
|
|
|
import android.util.Xml;
|
2012-01-17 15:55:31 -08:00
|
|
|
import android.view.IWindowManager;
|
2010-01-27 19:23:59 -08:00
|
|
|
import android.view.WindowManagerPolicy;
|
2010-01-12 18:14:19 -08:00
|
|
|
|
|
|
|
import java.io.File;
|
2010-02-26 17:25:54 -08:00
|
|
|
import java.io.FileDescriptor;
|
2010-01-12 18:14:19 -08:00
|
|
|
import java.io.FileInputStream;
|
2010-09-30 18:27:22 -07:00
|
|
|
import java.io.FileNotFoundException;
|
2010-01-12 18:14:19 -08:00
|
|
|
import java.io.FileOutputStream;
|
|
|
|
import java.io.IOException;
|
2010-02-26 17:25:54 -08:00
|
|
|
import java.io.PrintWriter;
|
2010-11-08 16:15:47 -08:00
|
|
|
import java.text.DateFormat;
|
2010-01-27 16:21:20 -08:00
|
|
|
import java.util.ArrayList;
|
2010-11-08 16:15:47 -08:00
|
|
|
import java.util.Date;
|
2010-01-27 16:21:20 -08:00
|
|
|
import java.util.HashMap;
|
2010-01-12 18:14:19 -08:00
|
|
|
import java.util.List;
|
2010-08-03 10:51:06 -07:00
|
|
|
import java.util.Set;
|
2010-01-12 18:14:19 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Implementation of the device policy APIs.
|
|
|
|
*/
|
|
|
|
public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
2012-09-14 23:20:08 -07:00
|
|
|
private static final String DEVICE_POLICIES_XML = "device_policies.xml";
|
|
|
|
|
2011-02-16 16:27:41 -08:00
|
|
|
private static final String TAG = "DevicePolicyManagerService";
|
2010-11-08 16:15:47 -08:00
|
|
|
|
2011-02-16 16:27:41 -08:00
|
|
|
private static final int REQUEST_EXPIRE_PASSWORD = 5571;
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
private static final long MS_PER_DAY = 86400 * 1000;
|
|
|
|
|
|
|
|
private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * MS_PER_DAY; // 5 days, in ms
|
2010-11-08 16:15:47 -08:00
|
|
|
|
|
|
|
protected static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION
|
|
|
|
= "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION";
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
private static final boolean DBG = false;
|
2010-11-08 16:15:47 -08:00
|
|
|
|
2010-02-19 17:02:21 -08:00
|
|
|
final Context mContext;
|
2010-10-15 18:45:07 -07:00
|
|
|
final PowerManager.WakeLock mWakeLock;
|
2010-01-12 18:14:19 -08:00
|
|
|
|
2010-01-20 13:37:26 -08:00
|
|
|
IPowerManager mIPowerManager;
|
2012-01-17 15:55:31 -08:00
|
|
|
IWindowManager mIWindowManager;
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public static class DevicePolicyData {
|
|
|
|
int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
|
|
|
|
int mActivePasswordLength = 0;
|
|
|
|
int mActivePasswordUpperCase = 0;
|
|
|
|
int mActivePasswordLowerCase = 0;
|
|
|
|
int mActivePasswordLetters = 0;
|
|
|
|
int mActivePasswordNumeric = 0;
|
|
|
|
int mActivePasswordSymbols = 0;
|
|
|
|
int mActivePasswordNonLetter = 0;
|
|
|
|
int mFailedPasswordAttempts = 0;
|
|
|
|
|
|
|
|
int mUserHandle;;
|
|
|
|
int mPasswordOwner = -1;
|
|
|
|
long mLastMaximumTimeToLock = -1;
|
|
|
|
|
|
|
|
final HashMap<ComponentName, ActiveAdmin> mAdminMap
|
|
|
|
= new HashMap<ComponentName, ActiveAdmin>();
|
|
|
|
final ArrayList<ActiveAdmin> mAdminList
|
|
|
|
= new ArrayList<ActiveAdmin>();
|
|
|
|
|
|
|
|
public DevicePolicyData(int userHandle) {
|
|
|
|
mUserHandle = userHandle;
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
final SparseArray<DevicePolicyData> mUserData = new SparseArray<DevicePolicyData>();
|
2012-06-15 17:05:25 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
Handler mHandler = new Handler();
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-11-08 16:15:47 -08:00
|
|
|
BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
|
|
|
@Override
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
2012-09-14 23:20:08 -07:00
|
|
|
final String action = intent.getAction();
|
|
|
|
final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
|
|
|
|
getSendingUserId());
|
2010-11-08 16:15:47 -08:00
|
|
|
if (Intent.ACTION_BOOT_COMPLETED.equals(action)
|
|
|
|
|| ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) {
|
2012-09-14 23:20:08 -07:00
|
|
|
Slog.v(TAG, "Sending password expiration notifications for action " + action
|
|
|
|
+ " for user " + userHandle);
|
2010-11-08 16:15:47 -08:00
|
|
|
mHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
2012-09-14 23:20:08 -07:00
|
|
|
handlePasswordExpirationNotification(getUserData(userHandle));
|
2010-11-08 16:15:47 -08:00
|
|
|
}
|
|
|
|
});
|
2012-09-14 23:20:08 -07:00
|
|
|
} else if (Intent.ACTION_USER_REMOVED.equals(action)) {
|
|
|
|
removeUserData(userHandle);
|
|
|
|
} else if (Intent.ACTION_USER_STARTED.equals(action)
|
|
|
|
|| Intent.ACTION_PACKAGE_CHANGED.equals(action)
|
|
|
|
|| Intent.ACTION_PACKAGE_REMOVED.equals(action)
|
|
|
|
|| Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
|
|
|
|
|
|
|
|
if (Intent.ACTION_USER_STARTED.equals(action)) {
|
|
|
|
// Reset the policy data
|
|
|
|
synchronized (DevicePolicyManagerService.this) {
|
|
|
|
mUserData.remove(userHandle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
handlePackagesChanged(userHandle);
|
2010-11-08 16:15:47 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2010-01-12 18:14:19 -08:00
|
|
|
static class ActiveAdmin {
|
2010-01-26 18:01:04 -08:00
|
|
|
final DeviceAdminInfo info;
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-29 10:38:29 -08:00
|
|
|
int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
|
2011-05-25 10:48:28 -07:00
|
|
|
|
|
|
|
static final int DEF_MINIMUM_PASSWORD_LENGTH = 0;
|
|
|
|
int minimumPasswordLength = DEF_MINIMUM_PASSWORD_LENGTH;
|
|
|
|
|
|
|
|
static final int DEF_PASSWORD_HISTORY_LENGTH = 0;
|
|
|
|
int passwordHistoryLength = DEF_PASSWORD_HISTORY_LENGTH;
|
|
|
|
|
|
|
|
static final int DEF_MINIMUM_PASSWORD_UPPER_CASE = 0;
|
|
|
|
int minimumPasswordUpperCase = DEF_MINIMUM_PASSWORD_UPPER_CASE;
|
|
|
|
|
|
|
|
static final int DEF_MINIMUM_PASSWORD_LOWER_CASE = 0;
|
|
|
|
int minimumPasswordLowerCase = DEF_MINIMUM_PASSWORD_LOWER_CASE;
|
|
|
|
|
|
|
|
static final int DEF_MINIMUM_PASSWORD_LETTERS = 1;
|
2011-05-26 11:45:00 -07:00
|
|
|
int minimumPasswordLetters = DEF_MINIMUM_PASSWORD_LETTERS;
|
2011-05-25 10:48:28 -07:00
|
|
|
|
|
|
|
static final int DEF_MINIMUM_PASSWORD_NUMERIC = 1;
|
|
|
|
int minimumPasswordNumeric = DEF_MINIMUM_PASSWORD_NUMERIC;
|
|
|
|
|
|
|
|
static final int DEF_MINIMUM_PASSWORD_SYMBOLS = 1;
|
|
|
|
int minimumPasswordSymbols = DEF_MINIMUM_PASSWORD_SYMBOLS;
|
|
|
|
|
|
|
|
static final int DEF_MINIMUM_PASSWORD_NON_LETTER = 0;
|
|
|
|
int minimumPasswordNonLetter = DEF_MINIMUM_PASSWORD_NON_LETTER;
|
|
|
|
|
|
|
|
static final long DEF_MAXIMUM_TIME_TO_UNLOCK = 0;
|
|
|
|
long maximumTimeToUnlock = DEF_MAXIMUM_TIME_TO_UNLOCK;
|
|
|
|
|
|
|
|
static final int DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE = 0;
|
|
|
|
int maximumFailedPasswordsForWipe = DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE;
|
|
|
|
|
|
|
|
static final long DEF_PASSWORD_EXPIRATION_TIMEOUT = 0;
|
|
|
|
long passwordExpirationTimeout = DEF_PASSWORD_EXPIRATION_TIMEOUT;
|
|
|
|
|
|
|
|
static final long DEF_PASSWORD_EXPIRATION_DATE = 0;
|
|
|
|
long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE;
|
|
|
|
|
2012-09-19 23:16:50 -07:00
|
|
|
static final int DEF_KEYGUARD_FEATURES_DISABLED = 0; // none
|
|
|
|
int disabledKeyguardFeatures = DEF_KEYGUARD_FEATURES_DISABLED;
|
2012-08-31 17:19:10 -07:00
|
|
|
|
2011-01-17 12:47:31 -08:00
|
|
|
boolean encryptionRequested = false;
|
2011-05-09 16:05:33 -07:00
|
|
|
boolean disableCamera = false;
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-08-03 10:51:06 -07:00
|
|
|
// TODO: review implementation decisions with frameworks team
|
|
|
|
boolean specifiesGlobalProxy = false;
|
|
|
|
String globalProxySpec = null;
|
|
|
|
String globalProxyExclusionList = null;
|
|
|
|
|
2010-01-12 18:14:19 -08:00
|
|
|
ActiveAdmin(DeviceAdminInfo _info) {
|
|
|
|
info = _info;
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-12 18:14:19 -08:00
|
|
|
int getUid() { return info.getActivityInfo().applicationInfo.uid; }
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public UserHandle getUserHandle() {
|
|
|
|
return new UserHandle(UserHandle.getUserId(info.getActivityInfo().applicationInfo.uid));
|
|
|
|
}
|
|
|
|
|
2010-01-26 18:01:04 -08:00
|
|
|
void writeToXml(XmlSerializer out)
|
|
|
|
throws IllegalArgumentException, IllegalStateException, IOException {
|
2010-02-19 17:02:21 -08:00
|
|
|
out.startTag(null, "policies");
|
|
|
|
info.writePoliciesToXml(out);
|
|
|
|
out.endTag(null, "policies");
|
2010-01-29 10:38:29 -08:00
|
|
|
if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
|
|
|
|
out.startTag(null, "password-quality");
|
|
|
|
out.attribute(null, "value", Integer.toString(passwordQuality));
|
|
|
|
out.endTag(null, "password-quality");
|
2011-05-25 10:48:28 -07:00
|
|
|
if (minimumPasswordLength != DEF_MINIMUM_PASSWORD_LENGTH) {
|
2010-01-26 18:01:04 -08:00
|
|
|
out.startTag(null, "min-password-length");
|
|
|
|
out.attribute(null, "value", Integer.toString(minimumPasswordLength));
|
2010-05-20 16:18:05 -07:00
|
|
|
out.endTag(null, "min-password-length");
|
|
|
|
}
|
2011-05-25 10:48:28 -07:00
|
|
|
if(passwordHistoryLength != DEF_PASSWORD_HISTORY_LENGTH) {
|
2010-05-20 16:18:05 -07:00
|
|
|
out.startTag(null, "password-history-length");
|
|
|
|
out.attribute(null, "value", Integer.toString(passwordHistoryLength));
|
|
|
|
out.endTag(null, "password-history-length");
|
2010-01-26 18:01:04 -08:00
|
|
|
}
|
2011-05-25 10:48:28 -07:00
|
|
|
if (minimumPasswordUpperCase != DEF_MINIMUM_PASSWORD_UPPER_CASE) {
|
2010-05-24 17:10:56 -07:00
|
|
|
out.startTag(null, "min-password-uppercase");
|
|
|
|
out.attribute(null, "value", Integer.toString(minimumPasswordUpperCase));
|
|
|
|
out.endTag(null, "min-password-uppercase");
|
|
|
|
}
|
2011-05-25 10:48:28 -07:00
|
|
|
if (minimumPasswordLowerCase != DEF_MINIMUM_PASSWORD_LOWER_CASE) {
|
2010-05-24 17:10:56 -07:00
|
|
|
out.startTag(null, "min-password-lowercase");
|
|
|
|
out.attribute(null, "value", Integer.toString(minimumPasswordLowerCase));
|
|
|
|
out.endTag(null, "min-password-lowercase");
|
|
|
|
}
|
2011-05-25 10:48:28 -07:00
|
|
|
if (minimumPasswordLetters != DEF_MINIMUM_PASSWORD_LETTERS) {
|
2010-05-24 17:10:56 -07:00
|
|
|
out.startTag(null, "min-password-letters");
|
|
|
|
out.attribute(null, "value", Integer.toString(minimumPasswordLetters));
|
|
|
|
out.endTag(null, "min-password-letters");
|
|
|
|
}
|
2011-05-25 10:48:28 -07:00
|
|
|
if (minimumPasswordNumeric != DEF_MINIMUM_PASSWORD_NUMERIC) {
|
2010-05-24 17:10:56 -07:00
|
|
|
out.startTag(null, "min-password-numeric");
|
|
|
|
out.attribute(null, "value", Integer.toString(minimumPasswordNumeric));
|
|
|
|
out.endTag(null, "min-password-numeric");
|
|
|
|
}
|
2011-05-25 10:48:28 -07:00
|
|
|
if (minimumPasswordSymbols != DEF_MINIMUM_PASSWORD_SYMBOLS) {
|
2010-05-24 17:10:56 -07:00
|
|
|
out.startTag(null, "min-password-symbols");
|
|
|
|
out.attribute(null, "value", Integer.toString(minimumPasswordSymbols));
|
|
|
|
out.endTag(null, "min-password-symbols");
|
|
|
|
}
|
2011-05-25 10:48:28 -07:00
|
|
|
if (minimumPasswordNonLetter > DEF_MINIMUM_PASSWORD_NON_LETTER) {
|
2010-06-04 17:15:02 -07:00
|
|
|
out.startTag(null, "min-password-nonletter");
|
|
|
|
out.attribute(null, "value", Integer.toString(minimumPasswordNonLetter));
|
|
|
|
out.endTag(null, "min-password-nonletter");
|
|
|
|
}
|
2010-01-26 18:01:04 -08:00
|
|
|
}
|
2011-05-25 10:48:28 -07:00
|
|
|
if (maximumTimeToUnlock != DEF_MAXIMUM_TIME_TO_UNLOCK) {
|
2010-01-26 18:01:04 -08:00
|
|
|
out.startTag(null, "max-time-to-unlock");
|
|
|
|
out.attribute(null, "value", Long.toString(maximumTimeToUnlock));
|
|
|
|
out.endTag(null, "max-time-to-unlock");
|
|
|
|
}
|
2011-05-25 10:48:28 -07:00
|
|
|
if (maximumFailedPasswordsForWipe != DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
|
2010-01-26 18:01:04 -08:00
|
|
|
out.startTag(null, "max-failed-password-wipe");
|
|
|
|
out.attribute(null, "value", Integer.toString(maximumFailedPasswordsForWipe));
|
|
|
|
out.endTag(null, "max-failed-password-wipe");
|
|
|
|
}
|
2010-08-03 10:51:06 -07:00
|
|
|
if (specifiesGlobalProxy) {
|
|
|
|
out.startTag(null, "specifies-global-proxy");
|
|
|
|
out.attribute(null, "value", Boolean.toString(specifiesGlobalProxy));
|
|
|
|
out.endTag(null, "specifies_global_proxy");
|
|
|
|
if (globalProxySpec != null) {
|
|
|
|
out.startTag(null, "global-proxy-spec");
|
|
|
|
out.attribute(null, "value", globalProxySpec);
|
|
|
|
out.endTag(null, "global-proxy-spec");
|
|
|
|
}
|
|
|
|
if (globalProxyExclusionList != null) {
|
|
|
|
out.startTag(null, "global-proxy-exclusion-list");
|
|
|
|
out.attribute(null, "value", globalProxyExclusionList);
|
|
|
|
out.endTag(null, "global-proxy-exclusion-list");
|
|
|
|
}
|
|
|
|
}
|
2011-05-25 10:48:28 -07:00
|
|
|
if (passwordExpirationTimeout != DEF_PASSWORD_EXPIRATION_TIMEOUT) {
|
2010-11-08 16:15:47 -08:00
|
|
|
out.startTag(null, "password-expiration-timeout");
|
|
|
|
out.attribute(null, "value", Long.toString(passwordExpirationTimeout));
|
|
|
|
out.endTag(null, "password-expiration-timeout");
|
|
|
|
}
|
2011-05-25 10:48:28 -07:00
|
|
|
if (passwordExpirationDate != DEF_PASSWORD_EXPIRATION_DATE) {
|
2010-11-08 16:15:47 -08:00
|
|
|
out.startTag(null, "password-expiration-date");
|
|
|
|
out.attribute(null, "value", Long.toString(passwordExpirationDate));
|
|
|
|
out.endTag(null, "password-expiration-date");
|
|
|
|
}
|
2011-01-17 12:47:31 -08:00
|
|
|
if (encryptionRequested) {
|
|
|
|
out.startTag(null, "encryption-requested");
|
|
|
|
out.attribute(null, "value", Boolean.toString(encryptionRequested));
|
|
|
|
out.endTag(null, "encryption-requested");
|
|
|
|
}
|
2011-05-09 16:05:33 -07:00
|
|
|
if (disableCamera) {
|
|
|
|
out.startTag(null, "disable-camera");
|
|
|
|
out.attribute(null, "value", Boolean.toString(disableCamera));
|
|
|
|
out.endTag(null, "disable-camera");
|
|
|
|
}
|
2012-09-19 23:16:50 -07:00
|
|
|
if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
|
|
|
|
out.startTag(null, "disable-keyguard-features");
|
|
|
|
out.attribute(null, "value", Integer.toString(disabledKeyguardFeatures));
|
|
|
|
out.endTag(null, "disable-keyguard-features");
|
2012-08-31 17:19:10 -07:00
|
|
|
}
|
2010-01-26 18:01:04 -08:00
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-26 18:01:04 -08:00
|
|
|
void readFromXml(XmlPullParser parser)
|
|
|
|
throws XmlPullParserException, IOException {
|
|
|
|
int outerDepth = parser.getDepth();
|
|
|
|
int type;
|
|
|
|
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
|
|
|
|
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
|
|
|
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
String tag = parser.getName();
|
2010-02-19 17:02:21 -08:00
|
|
|
if ("policies".equals(tag)) {
|
|
|
|
info.readPoliciesFromXml(parser);
|
|
|
|
} else if ("password-quality".equals(tag)) {
|
2010-01-29 10:38:29 -08:00
|
|
|
passwordQuality = Integer.parseInt(
|
2010-01-26 18:01:04 -08:00
|
|
|
parser.getAttributeValue(null, "value"));
|
|
|
|
} else if ("min-password-length".equals(tag)) {
|
|
|
|
minimumPasswordLength = Integer.parseInt(
|
|
|
|
parser.getAttributeValue(null, "value"));
|
2010-05-20 16:18:05 -07:00
|
|
|
} else if ("password-history-length".equals(tag)) {
|
|
|
|
passwordHistoryLength = Integer.parseInt(
|
|
|
|
parser.getAttributeValue(null, "value"));
|
2010-05-24 17:10:56 -07:00
|
|
|
} else if ("min-password-uppercase".equals(tag)) {
|
|
|
|
minimumPasswordUpperCase = Integer.parseInt(
|
|
|
|
parser.getAttributeValue(null, "value"));
|
|
|
|
} else if ("min-password-lowercase".equals(tag)) {
|
|
|
|
minimumPasswordLowerCase = Integer.parseInt(
|
|
|
|
parser.getAttributeValue(null, "value"));
|
|
|
|
} else if ("min-password-letters".equals(tag)) {
|
|
|
|
minimumPasswordLetters = Integer.parseInt(
|
|
|
|
parser.getAttributeValue(null, "value"));
|
|
|
|
} else if ("min-password-numeric".equals(tag)) {
|
|
|
|
minimumPasswordNumeric = Integer.parseInt(
|
|
|
|
parser.getAttributeValue(null, "value"));
|
|
|
|
} else if ("min-password-symbols".equals(tag)) {
|
|
|
|
minimumPasswordSymbols = Integer.parseInt(
|
|
|
|
parser.getAttributeValue(null, "value"));
|
2010-06-04 17:15:02 -07:00
|
|
|
} else if ("min-password-nonletter".equals(tag)) {
|
|
|
|
minimumPasswordNonLetter = Integer.parseInt(
|
|
|
|
parser.getAttributeValue(null, "value"));
|
2010-01-26 18:01:04 -08:00
|
|
|
} else if ("max-time-to-unlock".equals(tag)) {
|
|
|
|
maximumTimeToUnlock = Long.parseLong(
|
|
|
|
parser.getAttributeValue(null, "value"));
|
|
|
|
} else if ("max-failed-password-wipe".equals(tag)) {
|
|
|
|
maximumFailedPasswordsForWipe = Integer.parseInt(
|
|
|
|
parser.getAttributeValue(null, "value"));
|
2010-08-03 10:51:06 -07:00
|
|
|
} else if ("specifies-global-proxy".equals(tag)) {
|
2011-01-17 12:47:31 -08:00
|
|
|
specifiesGlobalProxy = Boolean.parseBoolean(
|
2010-08-03 10:51:06 -07:00
|
|
|
parser.getAttributeValue(null, "value"));
|
|
|
|
} else if ("global-proxy-spec".equals(tag)) {
|
|
|
|
globalProxySpec =
|
|
|
|
parser.getAttributeValue(null, "value");
|
|
|
|
} else if ("global-proxy-exclusion-list".equals(tag)) {
|
|
|
|
globalProxyExclusionList =
|
|
|
|
parser.getAttributeValue(null, "value");
|
2010-11-08 16:15:47 -08:00
|
|
|
} else if ("password-expiration-timeout".equals(tag)) {
|
|
|
|
passwordExpirationTimeout = Long.parseLong(
|
|
|
|
parser.getAttributeValue(null, "value"));
|
|
|
|
} else if ("password-expiration-date".equals(tag)) {
|
|
|
|
passwordExpirationDate = Long.parseLong(
|
|
|
|
parser.getAttributeValue(null, "value"));
|
2011-01-17 12:47:31 -08:00
|
|
|
} else if ("encryption-requested".equals(tag)) {
|
|
|
|
encryptionRequested = Boolean.parseBoolean(
|
|
|
|
parser.getAttributeValue(null, "value"));
|
2011-05-09 16:05:33 -07:00
|
|
|
} else if ("disable-camera".equals(tag)) {
|
|
|
|
disableCamera = Boolean.parseBoolean(
|
|
|
|
parser.getAttributeValue(null, "value"));
|
2010-02-19 17:02:21 -08:00
|
|
|
} else {
|
2010-03-22 11:12:48 -07:00
|
|
|
Slog.w(TAG, "Unknown admin tag: " + tag);
|
2010-02-19 17:02:21 -08:00
|
|
|
}
|
|
|
|
XmlUtils.skipCurrentTag(parser);
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-02-26 17:25:54 -08:00
|
|
|
void dump(String prefix, PrintWriter pw) {
|
|
|
|
pw.print(prefix); pw.print("uid="); pw.println(getUid());
|
|
|
|
pw.print(prefix); pw.println("policies:");
|
|
|
|
ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies();
|
|
|
|
if (pols != null) {
|
|
|
|
for (int i=0; i<pols.size(); i++) {
|
|
|
|
pw.print(prefix); pw.print(" "); pw.println(pols.get(i).tag);
|
|
|
|
}
|
|
|
|
}
|
2010-03-22 11:12:48 -07:00
|
|
|
pw.print(prefix); pw.print("passwordQuality=0x");
|
2010-05-20 16:18:05 -07:00
|
|
|
pw.println(Integer.toHexString(passwordQuality));
|
|
|
|
pw.print(prefix); pw.print("minimumPasswordLength=");
|
2010-02-26 17:25:54 -08:00
|
|
|
pw.println(minimumPasswordLength);
|
2010-05-20 16:18:05 -07:00
|
|
|
pw.print(prefix); pw.print("passwordHistoryLength=");
|
|
|
|
pw.println(passwordHistoryLength);
|
2010-05-24 17:10:56 -07:00
|
|
|
pw.print(prefix); pw.print("minimumPasswordUpperCase=");
|
|
|
|
pw.println(minimumPasswordUpperCase);
|
|
|
|
pw.print(prefix); pw.print("minimumPasswordLowerCase=");
|
|
|
|
pw.println(minimumPasswordLowerCase);
|
|
|
|
pw.print(prefix); pw.print("minimumPasswordLetters=");
|
|
|
|
pw.println(minimumPasswordLetters);
|
|
|
|
pw.print(prefix); pw.print("minimumPasswordNumeric=");
|
|
|
|
pw.println(minimumPasswordNumeric);
|
|
|
|
pw.print(prefix); pw.print("minimumPasswordSymbols=");
|
|
|
|
pw.println(minimumPasswordSymbols);
|
2010-06-04 17:15:02 -07:00
|
|
|
pw.print(prefix); pw.print("minimumPasswordNonLetter=");
|
|
|
|
pw.println(minimumPasswordNonLetter);
|
2010-02-26 17:25:54 -08:00
|
|
|
pw.print(prefix); pw.print("maximumTimeToUnlock=");
|
|
|
|
pw.println(maximumTimeToUnlock);
|
|
|
|
pw.print(prefix); pw.print("maximumFailedPasswordsForWipe=");
|
|
|
|
pw.println(maximumFailedPasswordsForWipe);
|
2010-08-03 10:51:06 -07:00
|
|
|
pw.print(prefix); pw.print("specifiesGlobalProxy=");
|
|
|
|
pw.println(specifiesGlobalProxy);
|
2010-11-08 16:15:47 -08:00
|
|
|
pw.print(prefix); pw.print("passwordExpirationTimeout=");
|
|
|
|
pw.println(passwordExpirationTimeout);
|
|
|
|
pw.print(prefix); pw.print("passwordExpirationDate=");
|
|
|
|
pw.println(passwordExpirationDate);
|
2010-08-03 10:51:06 -07:00
|
|
|
if (globalProxySpec != null) {
|
|
|
|
pw.print(prefix); pw.print("globalProxySpec=");
|
|
|
|
pw.println(globalProxySpec);
|
|
|
|
}
|
|
|
|
if (globalProxyExclusionList != null) {
|
|
|
|
pw.print(prefix); pw.print("globalProxyEclusionList=");
|
|
|
|
pw.println(globalProxyExclusionList);
|
|
|
|
}
|
2011-01-17 12:47:31 -08:00
|
|
|
pw.print(prefix); pw.print("encryptionRequested=");
|
|
|
|
pw.println(encryptionRequested);
|
2011-05-09 16:05:33 -07:00
|
|
|
pw.print(prefix); pw.print("disableCamera=");
|
|
|
|
pw.println(disableCamera);
|
2010-02-26 17:25:54 -08:00
|
|
|
}
|
2010-02-19 17:02:21 -08:00
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
private void handlePackagesChanged(int userHandle) {
|
|
|
|
boolean removed = false;
|
|
|
|
Slog.d(TAG, "Handling package changes for user " + userHandle);
|
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
IPackageManager pm = AppGlobals.getPackageManager();
|
|
|
|
for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
|
|
|
|
ActiveAdmin aa = policy.mAdminList.get(i);
|
|
|
|
try {
|
|
|
|
if (pm.getPackageInfo(aa.info.getPackageName(), 0, userHandle) == null
|
|
|
|
|| pm.getReceiverInfo(aa.info.getComponent(), 0, userHandle) == null) {
|
|
|
|
removed = true;
|
|
|
|
policy.mAdminList.remove(i);
|
2010-02-26 17:25:54 -08:00
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
} catch (RemoteException re) {
|
|
|
|
// Shouldn't happen
|
2010-01-26 18:01:04 -08:00
|
|
|
}
|
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
if (removed) {
|
|
|
|
validatePasswordOwnerLocked(policy);
|
|
|
|
syncDeviceCapabilitiesLocked(policy);
|
|
|
|
saveSettingsLocked(policy.mUserHandle);
|
|
|
|
}
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-12 18:14:19 -08:00
|
|
|
/**
|
|
|
|
* Instantiates the service.
|
|
|
|
*/
|
|
|
|
public DevicePolicyManagerService(Context context) {
|
|
|
|
mContext = context;
|
2010-10-15 18:45:07 -07:00
|
|
|
mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE))
|
|
|
|
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM");
|
2010-11-08 16:15:47 -08:00
|
|
|
IntentFilter filter = new IntentFilter();
|
|
|
|
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
|
|
|
|
filter.addAction(ACTION_EXPIRED_PASSWORD_NOTIFICATION);
|
2012-09-14 23:20:08 -07:00
|
|
|
filter.addAction(Intent.ACTION_USER_REMOVED);
|
|
|
|
filter.addAction(Intent.ACTION_USER_STARTED);
|
|
|
|
context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
|
|
|
|
filter = new IntentFilter();
|
|
|
|
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
|
|
|
|
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
|
|
|
filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
|
|
|
|
filter.addDataScheme("package");
|
|
|
|
context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates and loads the policy data from xml.
|
|
|
|
* @param userHandle the user for whom to load the policy data
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
DevicePolicyData getUserData(int userHandle) {
|
|
|
|
synchronized (this) {
|
|
|
|
DevicePolicyData policy = mUserData.get(userHandle);
|
|
|
|
if (policy == null) {
|
|
|
|
policy = new DevicePolicyData(userHandle);
|
|
|
|
mUserData.append(userHandle, policy);
|
|
|
|
loadSettingsLocked(policy, userHandle);
|
|
|
|
}
|
|
|
|
return policy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void removeUserData(int userHandle) {
|
|
|
|
synchronized (this) {
|
|
|
|
if (userHandle == UserHandle.USER_OWNER) {
|
|
|
|
Slog.w(TAG, "Tried to remove device policy file for user 0! Ignoring.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DevicePolicyData policy = mUserData.get(userHandle);
|
|
|
|
if (policy != null) {
|
|
|
|
mUserData.remove(userHandle);
|
|
|
|
}
|
|
|
|
File policyFile = new File(Environment.getUserSystemDirectory(userHandle),
|
|
|
|
DEVICE_POLICIES_XML);
|
|
|
|
policyFile.delete();
|
|
|
|
Slog.i(TAG, "Removed device policy file " + policyFile.getAbsolutePath());
|
|
|
|
}
|
2010-11-08 16:15:47 -08:00
|
|
|
}
|
|
|
|
|
2010-11-29 17:43:32 -08:00
|
|
|
/**
|
|
|
|
* Set an alarm for an upcoming event - expiration warning, expiration, or post-expiration
|
|
|
|
* reminders. Clears alarm if no expirations are configured.
|
|
|
|
*/
|
2012-09-14 23:20:08 -07:00
|
|
|
protected void setExpirationAlarmCheckLocked(Context context, DevicePolicyData policy) {
|
|
|
|
final long expiration = getPasswordExpirationLocked(null, policy.mUserHandle);
|
2010-11-08 16:15:47 -08:00
|
|
|
final long now = System.currentTimeMillis();
|
|
|
|
final long timeToExpire = expiration - now;
|
|
|
|
final long alarmTime;
|
2010-11-29 17:43:32 -08:00
|
|
|
if (expiration == 0) {
|
|
|
|
// No expirations are currently configured: Cancel alarm.
|
|
|
|
alarmTime = 0;
|
|
|
|
} else if (timeToExpire <= 0) {
|
|
|
|
// The password has already expired: Repeat every 24 hours.
|
2010-11-08 16:15:47 -08:00
|
|
|
alarmTime = now + MS_PER_DAY;
|
2010-11-29 17:43:32 -08:00
|
|
|
} else {
|
|
|
|
// Selecting the next alarm time: Roll forward to the next 24 hour multiple before
|
|
|
|
// the expiration time.
|
|
|
|
long alarmInterval = timeToExpire % MS_PER_DAY;
|
|
|
|
if (alarmInterval == 0) {
|
|
|
|
alarmInterval = MS_PER_DAY;
|
|
|
|
}
|
|
|
|
alarmTime = now + alarmInterval;
|
2010-11-08 16:15:47 -08:00
|
|
|
}
|
|
|
|
|
2010-11-19 15:39:41 -08:00
|
|
|
long token = Binder.clearCallingIdentity();
|
|
|
|
try {
|
|
|
|
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
|
2012-09-14 23:20:08 -07:00
|
|
|
PendingIntent pi = PendingIntent.getBroadcastAsUser(context, REQUEST_EXPIRE_PASSWORD,
|
2010-11-19 15:39:41 -08:00
|
|
|
new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION),
|
2012-09-14 23:20:08 -07:00
|
|
|
PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT,
|
|
|
|
new UserHandle(policy.mUserHandle));
|
2010-11-19 15:39:41 -08:00
|
|
|
am.cancel(pi);
|
2010-11-29 17:43:32 -08:00
|
|
|
if (alarmTime != 0) {
|
|
|
|
am.set(AlarmManager.RTC, alarmTime, pi);
|
|
|
|
}
|
2010-11-19 15:39:41 -08:00
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(token);
|
|
|
|
}
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
|
2010-01-20 13:37:26 -08:00
|
|
|
private IPowerManager getIPowerManager() {
|
|
|
|
if (mIPowerManager == null) {
|
|
|
|
IBinder b = ServiceManager.getService(Context.POWER_SERVICE);
|
|
|
|
mIPowerManager = IPowerManager.Stub.asInterface(b);
|
|
|
|
}
|
|
|
|
return mIPowerManager;
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-01-17 15:55:31 -08:00
|
|
|
private IWindowManager getWindowManager() {
|
|
|
|
if (mIWindowManager == null) {
|
|
|
|
IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE);
|
|
|
|
mIWindowManager = IWindowManager.Stub.asInterface(b);
|
|
|
|
}
|
|
|
|
return mIWindowManager;
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle) {
|
|
|
|
ActiveAdmin admin = getUserData(userHandle).mAdminMap.get(who);
|
2010-01-26 18:01:04 -08:00
|
|
|
if (admin != null
|
|
|
|
&& who.getPackageName().equals(admin.info.getActivityInfo().packageName)
|
|
|
|
&& who.getClassName().equals(admin.info.getActivityInfo().name)) {
|
|
|
|
return admin;
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-27 19:23:59 -08:00
|
|
|
ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
|
2010-01-22 11:31:30 -08:00
|
|
|
throws SecurityException {
|
2010-01-27 19:23:59 -08:00
|
|
|
final int callingUid = Binder.getCallingUid();
|
2012-09-14 23:20:08 -07:00
|
|
|
final int userHandle = UserHandle.getUserId(callingUid);
|
|
|
|
final DevicePolicyData policy = getUserData(userHandle);
|
2010-01-27 19:23:59 -08:00
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminMap.get(who);
|
2010-01-27 19:23:59 -08:00
|
|
|
if (admin == null) {
|
|
|
|
throw new SecurityException("No active admin " + who);
|
|
|
|
}
|
|
|
|
if (admin.getUid() != callingUid) {
|
|
|
|
throw new SecurityException("Admin " + who + " is not owned by uid "
|
|
|
|
+ Binder.getCallingUid());
|
|
|
|
}
|
|
|
|
if (!admin.info.usesPolicy(reqPolicy)) {
|
|
|
|
throw new SecurityException("Admin " + admin.info.getComponent()
|
|
|
|
+ " did not specify uses-policy for: "
|
|
|
|
+ admin.info.getTagForPolicy(reqPolicy));
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
2010-01-27 16:21:20 -08:00
|
|
|
return admin;
|
2010-01-27 19:23:59 -08:00
|
|
|
} else {
|
2012-09-14 23:20:08 -07:00
|
|
|
final int N = policy.mAdminList.size();
|
2010-01-27 19:23:59 -08:00
|
|
|
for (int i=0; i<N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-01-27 19:23:59 -08:00
|
|
|
if (admin.getUid() == callingUid && admin.info.usesPolicy(reqPolicy)) {
|
|
|
|
return admin;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw new SecurityException("No active admin owned by uid "
|
|
|
|
+ Binder.getCallingUid() + " for policy #" + reqPolicy);
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
2010-01-26 18:01:04 -08:00
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-22 11:31:30 -08:00
|
|
|
void sendAdminCommandLocked(ActiveAdmin admin, String action) {
|
2011-05-25 10:48:28 -07:00
|
|
|
sendAdminCommandLocked(admin, action, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
void sendAdminCommandLocked(ActiveAdmin admin, String action, BroadcastReceiver result) {
|
2010-01-12 18:14:19 -08:00
|
|
|
Intent intent = new Intent(action);
|
2010-01-22 11:31:30 -08:00
|
|
|
intent.setComponent(admin.info.getComponent());
|
2010-11-08 16:15:47 -08:00
|
|
|
if (action.equals(DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING)) {
|
|
|
|
intent.putExtra("expiration", admin.passwordExpirationDate);
|
|
|
|
}
|
2011-05-25 10:48:28 -07:00
|
|
|
if (result != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
mContext.sendOrderedBroadcastAsUser(intent, admin.getUserHandle(),
|
2012-08-29 18:32:08 -07:00
|
|
|
null, result, mHandler, Activity.RESULT_OK, null, null);
|
2011-05-25 10:48:28 -07:00
|
|
|
} else {
|
2012-08-29 18:32:08 -07:00
|
|
|
mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
|
2011-05-25 10:48:28 -07:00
|
|
|
}
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
void sendAdminCommandLocked(String action, int reqPolicy, int userHandle) {
|
|
|
|
final DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
final int count = policy.mAdminList.size();
|
|
|
|
if (count > 0) {
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-01-27 16:21:20 -08:00
|
|
|
if (admin.info.usesPolicy(reqPolicy)) {
|
|
|
|
sendAdminCommandLocked(admin, action);
|
|
|
|
}
|
2010-01-22 11:31:30 -08:00
|
|
|
}
|
2010-01-21 16:29:00 -08:00
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
void removeActiveAdminLocked(final ComponentName adminReceiver, int userHandle) {
|
|
|
|
final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
|
2010-01-27 16:21:20 -08:00
|
|
|
if (admin != null) {
|
|
|
|
sendAdminCommandLocked(admin,
|
2011-05-25 10:48:28 -07:00
|
|
|
DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED,
|
|
|
|
new BroadcastReceiver() {
|
|
|
|
@Override
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
2012-06-15 17:05:25 -07:00
|
|
|
synchronized (DevicePolicyManagerService.this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
int userHandle = admin.getUserHandle().getIdentifier();
|
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
2011-05-25 10:48:28 -07:00
|
|
|
boolean doProxyCleanup = admin.info.usesPolicy(
|
|
|
|
DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mAdminList.remove(admin);
|
|
|
|
policy.mAdminMap.remove(adminReceiver);
|
|
|
|
validatePasswordOwnerLocked(policy);
|
|
|
|
syncDeviceCapabilitiesLocked(policy);
|
2011-05-25 10:48:28 -07:00
|
|
|
if (doProxyCleanup) {
|
2012-09-14 23:20:08 -07:00
|
|
|
resetGlobalProxyLocked(getUserData(userHandle));
|
2011-05-25 10:48:28 -07:00
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
|
|
|
updateMaximumTimeToLockLocked(policy);
|
2011-05-25 10:48:28 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public DeviceAdminInfo findAdmin(ComponentName adminName, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
Intent resolveIntent = new Intent();
|
|
|
|
resolveIntent.setComponent(adminName);
|
|
|
|
List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceivers(
|
2012-09-14 23:20:08 -07:00
|
|
|
resolveIntent, PackageManager.GET_META_DATA, userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
if (infos == null || infos.size() <= 0) {
|
|
|
|
throw new IllegalArgumentException("Unknown admin: " + adminName);
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-12 18:14:19 -08:00
|
|
|
try {
|
|
|
|
return new DeviceAdminInfo(mContext, infos.get(0));
|
|
|
|
} catch (XmlPullParserException e) {
|
2012-09-14 23:20:08 -07:00
|
|
|
Slog.w(TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName, e);
|
2010-01-12 18:14:19 -08:00
|
|
|
return null;
|
|
|
|
} catch (IOException e) {
|
2012-09-14 23:20:08 -07:00
|
|
|
Slog.w(TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName, e);
|
2010-01-12 18:14:19 -08:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
private static JournaledFile makeJournaledFile(int userHandle) {
|
|
|
|
final String base = userHandle == 0
|
|
|
|
? "/data/system/" + DEVICE_POLICIES_XML
|
|
|
|
: new File(Environment.getUserSystemDirectory(userHandle), DEVICE_POLICIES_XML)
|
|
|
|
.getAbsolutePath();
|
2010-01-12 18:14:19 -08:00
|
|
|
return new JournaledFile(new File(base), new File(base + ".tmp"));
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
private void saveSettingsLocked(int userHandle) {
|
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
JournaledFile journal = makeJournaledFile(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
FileOutputStream stream = null;
|
|
|
|
try {
|
|
|
|
stream = new FileOutputStream(journal.chooseForWrite(), false);
|
|
|
|
XmlSerializer out = new FastXmlSerializer();
|
|
|
|
out.setOutput(stream, "utf-8");
|
|
|
|
out.startDocument(null, true);
|
|
|
|
|
|
|
|
out.startTag(null, "policies");
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
final int N = policy.mAdminList.size();
|
2010-01-27 16:21:20 -08:00
|
|
|
for (int i=0; i<N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin ap = policy.mAdminList.get(i);
|
2010-01-27 16:21:20 -08:00
|
|
|
if (ap != null) {
|
|
|
|
out.startTag(null, "admin");
|
|
|
|
out.attribute(null, "name", ap.info.getComponent().flattenToString());
|
|
|
|
ap.writeToXml(out);
|
|
|
|
out.endTag(null, "admin");
|
|
|
|
}
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
if (policy.mPasswordOwner >= 0) {
|
2010-02-26 17:25:54 -08:00
|
|
|
out.startTag(null, "password-owner");
|
2012-09-14 23:20:08 -07:00
|
|
|
out.attribute(null, "value", Integer.toString(policy.mPasswordOwner));
|
2010-02-26 17:25:54 -08:00
|
|
|
out.endTag(null, "password-owner");
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
if (policy.mFailedPasswordAttempts != 0) {
|
2010-01-26 18:01:04 -08:00
|
|
|
out.startTag(null, "failed-password-attempts");
|
2012-09-14 23:20:08 -07:00
|
|
|
out.attribute(null, "value", Integer.toString(policy.mFailedPasswordAttempts));
|
2010-01-26 18:01:04 -08:00
|
|
|
out.endTag(null, "failed-password-attempts");
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
if (policy.mActivePasswordQuality != 0 || policy.mActivePasswordLength != 0
|
|
|
|
|| policy.mActivePasswordUpperCase != 0 || policy.mActivePasswordLowerCase != 0
|
|
|
|
|| policy.mActivePasswordLetters != 0 || policy.mActivePasswordNumeric != 0
|
|
|
|
|| policy.mActivePasswordSymbols != 0 || policy.mActivePasswordNonLetter != 0) {
|
2010-03-22 11:12:48 -07:00
|
|
|
out.startTag(null, "active-password");
|
2012-09-14 23:20:08 -07:00
|
|
|
out.attribute(null, "quality", Integer.toString(policy.mActivePasswordQuality));
|
|
|
|
out.attribute(null, "length", Integer.toString(policy.mActivePasswordLength));
|
|
|
|
out.attribute(null, "uppercase", Integer.toString(policy.mActivePasswordUpperCase));
|
|
|
|
out.attribute(null, "lowercase", Integer.toString(policy.mActivePasswordLowerCase));
|
|
|
|
out.attribute(null, "letters", Integer.toString(policy.mActivePasswordLetters));
|
2010-05-24 17:10:56 -07:00
|
|
|
out.attribute(null, "numeric", Integer
|
2012-09-14 23:20:08 -07:00
|
|
|
.toString(policy.mActivePasswordNumeric));
|
|
|
|
out.attribute(null, "symbols", Integer.toString(policy.mActivePasswordSymbols));
|
|
|
|
out.attribute(null, "nonletter", Integer.toString(policy.mActivePasswordNonLetter));
|
2010-03-22 11:12:48 -07:00
|
|
|
out.endTag(null, "active-password");
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-03-22 11:12:48 -07:00
|
|
|
out.endTag(null, "policies");
|
|
|
|
|
2010-01-12 18:14:19 -08:00
|
|
|
out.endDocument();
|
|
|
|
stream.close();
|
|
|
|
journal.commit();
|
2012-09-14 23:20:08 -07:00
|
|
|
sendChangedNotification(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
} catch (IOException e) {
|
|
|
|
try {
|
|
|
|
if (stream != null) {
|
|
|
|
stream.close();
|
|
|
|
}
|
|
|
|
} catch (IOException ex) {
|
|
|
|
// Ignore
|
|
|
|
}
|
|
|
|
journal.rollback();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
private void sendChangedNotification(int userHandle) {
|
2010-06-08 14:27:42 -07:00
|
|
|
Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
|
|
|
|
intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
|
2012-09-10 10:24:36 -07:00
|
|
|
long ident = Binder.clearCallingIdentity();
|
|
|
|
try {
|
2012-09-14 23:20:08 -07:00
|
|
|
mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle));
|
2012-09-10 10:24:36 -07:00
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(ident);
|
|
|
|
}
|
2010-06-08 14:27:42 -07:00
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
private void loadSettingsLocked(DevicePolicyData policy, int userHandle) {
|
|
|
|
JournaledFile journal = makeJournaledFile(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
FileInputStream stream = null;
|
|
|
|
File file = journal.chooseForRead();
|
|
|
|
try {
|
|
|
|
stream = new FileInputStream(file);
|
|
|
|
XmlPullParser parser = Xml.newPullParser();
|
|
|
|
parser.setInput(stream, null);
|
|
|
|
|
2010-01-26 18:01:04 -08:00
|
|
|
int type;
|
|
|
|
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
|
|
|
|
&& type != XmlPullParser.START_TAG) {
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
String tag = parser.getName();
|
2010-01-26 18:01:04 -08:00
|
|
|
if (!"policies".equals(tag)) {
|
|
|
|
throw new XmlPullParserException(
|
|
|
|
"Settings do not start with policies tag: found " + tag);
|
|
|
|
}
|
|
|
|
type = parser.next();
|
|
|
|
int outerDepth = parser.getDepth();
|
|
|
|
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
|
|
|
|
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
|
|
|
|
if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
tag = parser.getName();
|
|
|
|
if ("admin".equals(tag)) {
|
2010-02-04 17:38:14 -08:00
|
|
|
String name = parser.getAttributeValue(null, "name");
|
|
|
|
try {
|
|
|
|
DeviceAdminInfo dai = findAdmin(
|
2012-09-14 23:20:08 -07:00
|
|
|
ComponentName.unflattenFromString(name), userHandle);
|
|
|
|
if (DBG && (UserHandle.getUserId(dai.getActivityInfo().applicationInfo.uid)
|
|
|
|
!= userHandle)) {
|
|
|
|
Slog.w(TAG, "findAdmin returned an incorrect uid "
|
|
|
|
+ dai.getActivityInfo().applicationInfo.uid + " for user "
|
|
|
|
+ userHandle);
|
|
|
|
}
|
2010-02-04 17:38:14 -08:00
|
|
|
if (dai != null) {
|
|
|
|
ActiveAdmin ap = new ActiveAdmin(dai);
|
|
|
|
ap.readFromXml(parser);
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mAdminMap.put(ap.info.getComponent(), ap);
|
|
|
|
policy.mAdminList.add(ap);
|
2010-02-04 17:38:14 -08:00
|
|
|
}
|
|
|
|
} catch (RuntimeException e) {
|
2010-03-22 11:12:48 -07:00
|
|
|
Slog.w(TAG, "Failed loading admin " + name, e);
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
2010-01-26 18:01:04 -08:00
|
|
|
} else if ("failed-password-attempts".equals(tag)) {
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mFailedPasswordAttempts = Integer.parseInt(
|
2010-01-26 18:01:04 -08:00
|
|
|
parser.getAttributeValue(null, "value"));
|
2010-02-19 17:02:21 -08:00
|
|
|
XmlUtils.skipCurrentTag(parser);
|
2010-02-26 17:25:54 -08:00
|
|
|
} else if ("password-owner".equals(tag)) {
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mPasswordOwner = Integer.parseInt(
|
2010-02-26 17:25:54 -08:00
|
|
|
parser.getAttributeValue(null, "value"));
|
|
|
|
XmlUtils.skipCurrentTag(parser);
|
2010-03-22 11:12:48 -07:00
|
|
|
} else if ("active-password".equals(tag)) {
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mActivePasswordQuality = Integer.parseInt(
|
2010-03-22 11:12:48 -07:00
|
|
|
parser.getAttributeValue(null, "quality"));
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mActivePasswordLength = Integer.parseInt(
|
2010-03-22 11:12:48 -07:00
|
|
|
parser.getAttributeValue(null, "length"));
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mActivePasswordUpperCase = Integer.parseInt(
|
2010-05-24 17:10:56 -07:00
|
|
|
parser.getAttributeValue(null, "uppercase"));
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mActivePasswordLowerCase = Integer.parseInt(
|
2010-05-24 17:10:56 -07:00
|
|
|
parser.getAttributeValue(null, "lowercase"));
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mActivePasswordLetters = Integer.parseInt(
|
2010-05-24 17:10:56 -07:00
|
|
|
parser.getAttributeValue(null, "letters"));
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mActivePasswordNumeric = Integer.parseInt(
|
2010-05-24 17:10:56 -07:00
|
|
|
parser.getAttributeValue(null, "numeric"));
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mActivePasswordSymbols = Integer.parseInt(
|
2010-05-24 17:10:56 -07:00
|
|
|
parser.getAttributeValue(null, "symbols"));
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mActivePasswordNonLetter = Integer.parseInt(
|
2010-06-04 17:15:02 -07:00
|
|
|
parser.getAttributeValue(null, "nonletter"));
|
2010-03-22 11:12:48 -07:00
|
|
|
XmlUtils.skipCurrentTag(parser);
|
2010-02-19 17:02:21 -08:00
|
|
|
} else {
|
2010-03-22 11:12:48 -07:00
|
|
|
Slog.w(TAG, "Unknown tag: " + tag);
|
2010-02-19 17:02:21 -08:00
|
|
|
XmlUtils.skipCurrentTag(parser);
|
2010-01-26 18:01:04 -08:00
|
|
|
}
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
} catch (NullPointerException e) {
|
2010-03-22 11:12:48 -07:00
|
|
|
Slog.w(TAG, "failed parsing " + file + " " + e);
|
2010-01-12 18:14:19 -08:00
|
|
|
} catch (NumberFormatException e) {
|
2010-03-22 11:12:48 -07:00
|
|
|
Slog.w(TAG, "failed parsing " + file + " " + e);
|
2010-01-12 18:14:19 -08:00
|
|
|
} catch (XmlPullParserException e) {
|
2010-03-22 11:12:48 -07:00
|
|
|
Slog.w(TAG, "failed parsing " + file + " " + e);
|
2010-09-30 18:27:22 -07:00
|
|
|
} catch (FileNotFoundException e) {
|
|
|
|
// Don't be noisy, this is normal if we haven't defined any policies.
|
2010-01-12 18:14:19 -08:00
|
|
|
} catch (IOException e) {
|
2010-03-22 11:12:48 -07:00
|
|
|
Slog.w(TAG, "failed parsing " + file + " " + e);
|
2010-01-12 18:14:19 -08:00
|
|
|
} catch (IndexOutOfBoundsException e) {
|
2010-03-22 11:12:48 -07:00
|
|
|
Slog.w(TAG, "failed parsing " + file + " " + e);
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (stream != null) {
|
|
|
|
stream.close();
|
|
|
|
}
|
|
|
|
} catch (IOException e) {
|
|
|
|
// Ignore
|
|
|
|
}
|
|
|
|
|
2010-03-22 11:12:48 -07:00
|
|
|
// Validate that what we stored for the password quality matches
|
|
|
|
// sufficiently what is currently set. Note that this is only
|
|
|
|
// a sanity check in case the two get out of sync; this should
|
|
|
|
// never normally happen.
|
|
|
|
LockPatternUtils utils = new LockPatternUtils(mContext);
|
2012-09-14 23:20:08 -07:00
|
|
|
if (utils.getActivePasswordQuality() < policy.mActivePasswordQuality) {
|
2010-03-22 11:12:48 -07:00
|
|
|
Slog.w(TAG, "Active password quality 0x"
|
2012-09-14 23:20:08 -07:00
|
|
|
+ Integer.toHexString(policy.mActivePasswordQuality)
|
2010-03-22 11:12:48 -07:00
|
|
|
+ " does not match actual quality 0x"
|
|
|
|
+ Integer.toHexString(utils.getActivePasswordQuality()));
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
|
|
|
|
policy.mActivePasswordLength = 0;
|
|
|
|
policy.mActivePasswordUpperCase = 0;
|
|
|
|
policy.mActivePasswordLowerCase = 0;
|
|
|
|
policy.mActivePasswordLetters = 0;
|
|
|
|
policy.mActivePasswordNumeric = 0;
|
|
|
|
policy.mActivePasswordSymbols = 0;
|
|
|
|
policy.mActivePasswordNonLetter = 0;
|
2010-03-22 11:12:48 -07:00
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
validatePasswordOwnerLocked(policy);
|
|
|
|
syncDeviceCapabilitiesLocked(policy);
|
|
|
|
updateMaximumTimeToLockLocked(policy);
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
|
2010-03-22 11:12:48 -07:00
|
|
|
static void validateQualityConstant(int quality) {
|
|
|
|
switch (quality) {
|
|
|
|
case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
|
2011-12-21 17:02:32 -05:00
|
|
|
case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK:
|
2010-03-22 11:12:48 -07:00
|
|
|
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
|
|
|
|
case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
|
|
|
|
case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
|
|
|
|
case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
|
2010-05-24 17:10:56 -07:00
|
|
|
case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
|
2010-03-22 11:12:48 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
throw new IllegalArgumentException("Invalid quality constant: 0x"
|
|
|
|
+ Integer.toHexString(quality));
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
void validatePasswordOwnerLocked(DevicePolicyData policy) {
|
|
|
|
if (policy.mPasswordOwner >= 0) {
|
2010-02-26 17:25:54 -08:00
|
|
|
boolean haveOwner = false;
|
2012-09-14 23:20:08 -07:00
|
|
|
for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
|
|
|
|
if (policy.mAdminList.get(i).getUid() == policy.mPasswordOwner) {
|
2010-02-26 17:25:54 -08:00
|
|
|
haveOwner = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!haveOwner) {
|
2012-09-14 23:20:08 -07:00
|
|
|
Slog.w(TAG, "Previous password owner " + policy.mPasswordOwner
|
2010-02-26 17:25:54 -08:00
|
|
|
+ " no longer active; disabling");
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mPasswordOwner = -1;
|
2010-02-26 17:25:54 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2011-05-09 16:05:33 -07:00
|
|
|
/**
|
|
|
|
* Pushes down policy information to the system for any policies related to general device
|
|
|
|
* capabilities that need to be enforced by lower level services (e.g. Camera services).
|
|
|
|
*/
|
2012-09-14 23:20:08 -07:00
|
|
|
void syncDeviceCapabilitiesLocked(DevicePolicyData policy) {
|
2011-05-09 16:05:33 -07:00
|
|
|
// Ensure the status of the camera is synced down to the system. Interested native services
|
|
|
|
// should monitor this value and act accordingly.
|
|
|
|
boolean systemState = SystemProperties.getBoolean(SYSTEM_PROP_DISABLE_CAMERA, false);
|
2012-09-14 23:20:08 -07:00
|
|
|
boolean cameraDisabled = getCameraDisabled(null, policy.mUserHandle);
|
2011-05-09 16:05:33 -07:00
|
|
|
if (cameraDisabled != systemState) {
|
|
|
|
long token = Binder.clearCallingIdentity();
|
|
|
|
try {
|
|
|
|
String value = cameraDisabled ? "1" : "0";
|
|
|
|
Slog.v(TAG, "Change in camera state ["
|
|
|
|
+ SYSTEM_PROP_DISABLE_CAMERA + "] = " + value);
|
|
|
|
SystemProperties.set(SYSTEM_PROP_DISABLE_CAMERA, value);
|
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(token);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-12 18:14:19 -08:00
|
|
|
public void systemReady() {
|
|
|
|
synchronized (this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
loadSettingsLocked(getUserData(UserHandle.USER_OWNER), UserHandle.USER_OWNER);
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
private void handlePasswordExpirationNotification(DevicePolicyData policy) {
|
2010-11-08 16:15:47 -08:00
|
|
|
synchronized (this) {
|
|
|
|
final long now = System.currentTimeMillis();
|
2012-09-14 23:20:08 -07:00
|
|
|
final int N = policy.mAdminList.size();
|
2010-11-08 16:15:47 -08:00
|
|
|
if (N <= 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (int i=0; i < N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-11-08 16:15:47 -08:00
|
|
|
if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)
|
|
|
|
&& admin.passwordExpirationTimeout > 0L
|
|
|
|
&& admin.passwordExpirationDate > 0L
|
2010-11-29 17:43:32 -08:00
|
|
|
&& now >= admin.passwordExpirationDate - EXPIRATION_GRACE_PERIOD_MS) {
|
2010-11-08 16:15:47 -08:00
|
|
|
sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING);
|
|
|
|
}
|
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
setExpirationAlarmCheckLocked(mContext, policy);
|
2010-11-08 16:15:47 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-08 15:56:45 -08:00
|
|
|
/**
|
|
|
|
* @param adminReceiver The admin to add
|
|
|
|
* @param refreshing true = update an active admin, no error
|
|
|
|
*/
|
2012-09-14 23:20:08 -07:00
|
|
|
public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle) {
|
2010-01-12 18:14:19 -08:00
|
|
|
mContext.enforceCallingOrSelfPermission(
|
|
|
|
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
|
2012-09-14 23:20:08 -07:00
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
DeviceAdminInfo info = findAdmin(adminReceiver, userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
if (info == null) {
|
|
|
|
throw new IllegalArgumentException("Bad admin: " + adminReceiver);
|
|
|
|
}
|
|
|
|
synchronized (this) {
|
|
|
|
long ident = Binder.clearCallingIdentity();
|
|
|
|
try {
|
2012-09-14 23:20:08 -07:00
|
|
|
if (!refreshing && getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null) {
|
2010-01-27 16:21:20 -08:00
|
|
|
throw new IllegalArgumentException("Admin is already added");
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
2010-12-08 15:56:45 -08:00
|
|
|
ActiveAdmin newAdmin = new ActiveAdmin(info);
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mAdminMap.put(adminReceiver, newAdmin);
|
2010-12-08 15:56:45 -08:00
|
|
|
int replaceIndex = -1;
|
|
|
|
if (refreshing) {
|
2012-09-14 23:20:08 -07:00
|
|
|
final int N = policy.mAdminList.size();
|
2010-12-08 15:56:45 -08:00
|
|
|
for (int i=0; i < N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin oldAdmin = policy.mAdminList.get(i);
|
2010-12-08 15:56:45 -08:00
|
|
|
if (oldAdmin.info.getComponent().equals(adminReceiver)) {
|
|
|
|
replaceIndex = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (replaceIndex == -1) {
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mAdminList.add(newAdmin);
|
2010-12-08 15:56:45 -08:00
|
|
|
} else {
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mAdminList.set(replaceIndex, newAdmin);
|
2010-12-08 15:56:45 -08:00
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
2010-12-08 15:56:45 -08:00
|
|
|
sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED);
|
2010-01-12 18:14:19 -08:00
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(ident);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public boolean isAdminActive(ComponentName adminReceiver, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-27 16:21:20 -08:00
|
|
|
synchronized (this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null;
|
2010-01-27 16:21:20 -08:00
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public boolean hasGrantedPolicy(ComponentName adminReceiver, int policyId, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-12-08 15:56:45 -08:00
|
|
|
synchronized (this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
|
2010-12-08 15:56:45 -08:00
|
|
|
if (administrator == null) {
|
|
|
|
throw new SecurityException("No active admin " + adminReceiver);
|
|
|
|
}
|
|
|
|
return administrator.info.usesPolicy(policyId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public List<ComponentName> getActiveAdmins(int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
synchronized (this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
final int N = policy.mAdminList.size();
|
2010-01-27 16:21:20 -08:00
|
|
|
if (N <= 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
ArrayList<ComponentName> res = new ArrayList<ComponentName>(N);
|
|
|
|
for (int i=0; i<N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
res.add(policy.mAdminList.get(i).info.getComponent());
|
2010-01-27 16:21:20 -08:00
|
|
|
}
|
|
|
|
return res;
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public boolean packageHasActiveAdmins(String packageName, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-02-19 17:02:21 -08:00
|
|
|
synchronized (this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
final int N = policy.mAdminList.size();
|
2010-02-19 17:02:21 -08:00
|
|
|
for (int i=0; i<N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
if (policy.mAdminList.get(i).info.getPackageName().equals(packageName)) {
|
2010-02-19 17:02:21 -08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void removeActiveAdmin(ComponentName adminReceiver, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
synchronized (this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
|
2010-01-27 16:21:20 -08:00
|
|
|
if (admin == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (admin.getUid() != Binder.getCallingUid()) {
|
2010-01-12 18:14:19 -08:00
|
|
|
mContext.enforceCallingOrSelfPermission(
|
|
|
|
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
|
|
|
|
}
|
|
|
|
long ident = Binder.clearCallingIdentity();
|
|
|
|
try {
|
2012-09-14 23:20:08 -07:00
|
|
|
removeActiveAdminLocked(adminReceiver, userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(ident);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void setPasswordQuality(ComponentName who, int quality, int userHandle) {
|
2010-03-22 11:12:48 -07:00
|
|
|
validateQualityConstant(quality);
|
2012-09-14 23:20:08 -07:00
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-12 18:14:19 -08:00
|
|
|
synchronized (this) {
|
|
|
|
if (who == null) {
|
|
|
|
throw new NullPointerException("ComponentName is null");
|
|
|
|
}
|
2010-01-22 11:31:30 -08:00
|
|
|
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
|
|
|
|
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
|
2010-03-22 11:12:48 -07:00
|
|
|
if (ap.passwordQuality != quality) {
|
|
|
|
ap.passwordQuality = quality;
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public int getPasswordQuality(ComponentName who, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
synchronized (this) {
|
2010-01-29 10:38:29 -08:00
|
|
|
int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-27 19:23:59 -08:00
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
|
2010-01-29 10:38:29 -08:00
|
|
|
return admin != null ? admin.passwordQuality : mode;
|
2010-01-27 19:23:59 -08:00
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
final int N = policy.mAdminList.size();
|
2010-01-27 16:21:20 -08:00
|
|
|
for (int i=0; i<N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-01-29 10:38:29 -08:00
|
|
|
if (mode < admin.passwordQuality) {
|
|
|
|
mode = admin.passwordQuality;
|
2010-01-27 16:21:20 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return mode;
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void setPasswordMinimumLength(ComponentName who, int length, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
synchronized (this) {
|
|
|
|
if (who == null) {
|
|
|
|
throw new NullPointerException("ComponentName is null");
|
|
|
|
}
|
2010-01-22 11:31:30 -08:00
|
|
|
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
|
|
|
|
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
|
2010-01-12 18:14:19 -08:00
|
|
|
if (ap.minimumPasswordLength != length) {
|
|
|
|
ap.minimumPasswordLength = length;
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public int getPasswordMinimumLength(ComponentName who, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
synchronized (this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
2010-01-27 16:21:20 -08:00
|
|
|
int length = 0;
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-27 19:23:59 -08:00
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
|
2010-01-27 19:23:59 -08:00
|
|
|
return admin != null ? admin.minimumPasswordLength : length;
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
final int N = policy.mAdminList.size();
|
2010-01-27 16:21:20 -08:00
|
|
|
for (int i=0; i<N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-01-27 16:21:20 -08:00
|
|
|
if (length < admin.minimumPasswordLength) {
|
|
|
|
length = admin.minimumPasswordLength;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return length;
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void setPasswordHistoryLength(ComponentName who, int length, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-05-20 16:18:05 -07:00
|
|
|
synchronized (this) {
|
|
|
|
if (who == null) {
|
|
|
|
throw new NullPointerException("ComponentName is null");
|
|
|
|
}
|
|
|
|
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
|
|
|
|
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
|
|
|
|
if (ap.passwordHistoryLength != length) {
|
|
|
|
ap.passwordHistoryLength = length;
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
2010-05-20 16:18:05 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public int getPasswordHistoryLength(ComponentName who, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-05-20 16:18:05 -07:00
|
|
|
synchronized (this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
2010-05-20 16:18:05 -07:00
|
|
|
int length = 0;
|
|
|
|
|
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
|
2010-05-20 16:18:05 -07:00
|
|
|
return admin != null ? admin.passwordHistoryLength : length;
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
final int N = policy.mAdminList.size();
|
2010-05-20 16:18:05 -07:00
|
|
|
for (int i = 0; i < N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-05-20 16:18:05 -07:00
|
|
|
if (length < admin.passwordHistoryLength) {
|
|
|
|
length = admin.passwordHistoryLength;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void setPasswordExpirationTimeout(ComponentName who, long timeout, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-11-08 16:15:47 -08:00
|
|
|
synchronized (this) {
|
|
|
|
if (who == null) {
|
|
|
|
throw new NullPointerException("ComponentName is null");
|
|
|
|
}
|
2010-11-19 15:39:41 -08:00
|
|
|
if (timeout < 0) {
|
|
|
|
throw new IllegalArgumentException("Timeout must be >= 0 ms");
|
2010-11-08 16:15:47 -08:00
|
|
|
}
|
|
|
|
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
|
|
|
|
DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD);
|
|
|
|
// Calling this API automatically bumps the expiration date
|
|
|
|
final long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L;
|
|
|
|
ap.passwordExpirationDate = expiration;
|
|
|
|
ap.passwordExpirationTimeout = timeout;
|
|
|
|
if (timeout > 0L) {
|
|
|
|
Slog.w(TAG, "setPasswordExpiration(): password will expire on "
|
|
|
|
+ DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)
|
|
|
|
.format(new Date(expiration)));
|
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
|
|
|
// in case this is the first one
|
|
|
|
setExpirationAlarmCheckLocked(mContext, getUserData(userHandle));
|
2010-11-08 16:15:47 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-29 17:43:32 -08:00
|
|
|
/**
|
|
|
|
* Return a single admin's expiration cycle time, or the min of all cycle times.
|
|
|
|
* Returns 0 if not configured.
|
|
|
|
*/
|
2012-09-14 23:20:08 -07:00
|
|
|
public long getPasswordExpirationTimeout(ComponentName who, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-11-08 16:15:47 -08:00
|
|
|
synchronized (this) {
|
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
|
2010-11-29 17:43:32 -08:00
|
|
|
return admin != null ? admin.passwordExpirationTimeout : 0L;
|
2010-11-08 16:15:47 -08:00
|
|
|
}
|
|
|
|
|
2010-11-29 17:43:32 -08:00
|
|
|
long timeout = 0L;
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
final int N = policy.mAdminList.size();
|
2010-11-08 16:15:47 -08:00
|
|
|
for (int i = 0; i < N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-11-08 16:15:47 -08:00
|
|
|
if (timeout == 0L || (admin.passwordExpirationTimeout != 0L
|
|
|
|
&& timeout > admin.passwordExpirationTimeout)) {
|
|
|
|
timeout = admin.passwordExpirationTimeout;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return timeout;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-29 17:43:32 -08:00
|
|
|
/**
|
|
|
|
* Return a single admin's expiration date/time, or the min (soonest) for all admins.
|
|
|
|
* Returns 0 if not configured.
|
|
|
|
*/
|
2012-09-14 23:20:08 -07:00
|
|
|
private long getPasswordExpirationLocked(ComponentName who, int userHandle) {
|
2010-11-08 16:15:47 -08:00
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
|
2010-11-29 17:43:32 -08:00
|
|
|
return admin != null ? admin.passwordExpirationDate : 0L;
|
2010-11-08 16:15:47 -08:00
|
|
|
}
|
|
|
|
|
2010-11-29 17:43:32 -08:00
|
|
|
long timeout = 0L;
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
final int N = policy.mAdminList.size();
|
2010-11-08 16:15:47 -08:00
|
|
|
for (int i = 0; i < N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-11-08 16:15:47 -08:00
|
|
|
if (timeout == 0L || (admin.passwordExpirationDate != 0
|
|
|
|
&& timeout > admin.passwordExpirationDate)) {
|
|
|
|
timeout = admin.passwordExpirationDate;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return timeout;
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public long getPasswordExpiration(ComponentName who, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-11-08 16:15:47 -08:00
|
|
|
synchronized (this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
return getPasswordExpirationLocked(who, userHandle);
|
2010-11-08 16:15:47 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void setPasswordMinimumUpperCase(ComponentName who, int length, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
synchronized (this) {
|
|
|
|
if (who == null) {
|
|
|
|
throw new NullPointerException("ComponentName is null");
|
|
|
|
}
|
|
|
|
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
|
|
|
|
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
|
|
|
|
if (ap.minimumPasswordUpperCase != length) {
|
|
|
|
ap.minimumPasswordUpperCase = length;
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public int getPasswordMinimumUpperCase(ComponentName who, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
synchronized (this) {
|
|
|
|
int length = 0;
|
|
|
|
|
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
return admin != null ? admin.minimumPasswordUpperCase : length;
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
final int N = policy.mAdminList.size();
|
2010-05-24 17:10:56 -07:00
|
|
|
for (int i=0; i<N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-05-24 17:10:56 -07:00
|
|
|
if (length < admin.minimumPasswordUpperCase) {
|
|
|
|
length = admin.minimumPasswordUpperCase;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void setPasswordMinimumLowerCase(ComponentName who, int length, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
synchronized (this) {
|
|
|
|
if (who == null) {
|
|
|
|
throw new NullPointerException("ComponentName is null");
|
|
|
|
}
|
|
|
|
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
|
|
|
|
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
|
|
|
|
if (ap.minimumPasswordLowerCase != length) {
|
|
|
|
ap.minimumPasswordLowerCase = length;
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public int getPasswordMinimumLowerCase(ComponentName who, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
synchronized (this) {
|
|
|
|
int length = 0;
|
|
|
|
|
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
return admin != null ? admin.minimumPasswordLowerCase : length;
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
final int N = policy.mAdminList.size();
|
2010-05-24 17:10:56 -07:00
|
|
|
for (int i=0; i<N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-05-24 17:10:56 -07:00
|
|
|
if (length < admin.minimumPasswordLowerCase) {
|
|
|
|
length = admin.minimumPasswordLowerCase;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void setPasswordMinimumLetters(ComponentName who, int length, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
synchronized (this) {
|
|
|
|
if (who == null) {
|
|
|
|
throw new NullPointerException("ComponentName is null");
|
|
|
|
}
|
|
|
|
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
|
|
|
|
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
|
|
|
|
if (ap.minimumPasswordLetters != length) {
|
|
|
|
ap.minimumPasswordLetters = length;
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public int getPasswordMinimumLetters(ComponentName who, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
synchronized (this) {
|
|
|
|
int length = 0;
|
|
|
|
|
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
return admin != null ? admin.minimumPasswordLetters : length;
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
final int N = policy.mAdminList.size();
|
2010-05-24 17:10:56 -07:00
|
|
|
for (int i=0; i<N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-05-24 17:10:56 -07:00
|
|
|
if (length < admin.minimumPasswordLetters) {
|
|
|
|
length = admin.minimumPasswordLetters;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void setPasswordMinimumNumeric(ComponentName who, int length, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
synchronized (this) {
|
|
|
|
if (who == null) {
|
|
|
|
throw new NullPointerException("ComponentName is null");
|
|
|
|
}
|
|
|
|
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
|
|
|
|
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
|
|
|
|
if (ap.minimumPasswordNumeric != length) {
|
|
|
|
ap.minimumPasswordNumeric = length;
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public int getPasswordMinimumNumeric(ComponentName who, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
synchronized (this) {
|
|
|
|
int length = 0;
|
|
|
|
|
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
return admin != null ? admin.minimumPasswordNumeric : length;
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
final int N = policy.mAdminList.size();
|
2010-05-24 17:10:56 -07:00
|
|
|
for (int i = 0; i < N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-05-24 17:10:56 -07:00
|
|
|
if (length < admin.minimumPasswordNumeric) {
|
|
|
|
length = admin.minimumPasswordNumeric;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void setPasswordMinimumSymbols(ComponentName who, int length, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
synchronized (this) {
|
|
|
|
if (who == null) {
|
|
|
|
throw new NullPointerException("ComponentName is null");
|
|
|
|
}
|
|
|
|
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
|
|
|
|
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
|
|
|
|
if (ap.minimumPasswordSymbols != length) {
|
|
|
|
ap.minimumPasswordSymbols = length;
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public int getPasswordMinimumSymbols(ComponentName who, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
synchronized (this) {
|
|
|
|
int length = 0;
|
|
|
|
|
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
return admin != null ? admin.minimumPasswordSymbols : length;
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
final int N = policy.mAdminList.size();
|
2010-05-24 17:10:56 -07:00
|
|
|
for (int i=0; i<N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-05-24 17:10:56 -07:00
|
|
|
if (length < admin.minimumPasswordSymbols) {
|
|
|
|
length = admin.minimumPasswordSymbols;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void setPasswordMinimumNonLetter(ComponentName who, int length, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-06-04 17:15:02 -07:00
|
|
|
synchronized (this) {
|
|
|
|
if (who == null) {
|
|
|
|
throw new NullPointerException("ComponentName is null");
|
|
|
|
}
|
|
|
|
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
|
|
|
|
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
|
|
|
|
if (ap.minimumPasswordNonLetter != length) {
|
|
|
|
ap.minimumPasswordNonLetter = length;
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
2010-06-04 17:15:02 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public int getPasswordMinimumNonLetter(ComponentName who, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-06-04 17:15:02 -07:00
|
|
|
synchronized (this) {
|
|
|
|
int length = 0;
|
|
|
|
|
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
|
2010-06-04 17:15:02 -07:00
|
|
|
return admin != null ? admin.minimumPasswordNonLetter : length;
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
final int N = policy.mAdminList.size();
|
2010-06-04 17:15:02 -07:00
|
|
|
for (int i=0; i<N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-06-04 17:15:02 -07:00
|
|
|
if (length < admin.minimumPasswordNonLetter) {
|
|
|
|
length = admin.minimumPasswordNonLetter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public boolean isActivePasswordSufficient(int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
synchronized (this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
// This API can only be called by an active device admin,
|
|
|
|
// so try to retrieve it to check that the caller is one.
|
2010-01-22 11:31:30 -08:00
|
|
|
getActiveAdminForCallerLocked(null,
|
|
|
|
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
|
2012-09-14 23:20:08 -07:00
|
|
|
if (policy.mActivePasswordQuality < getPasswordQuality(null, userHandle)
|
|
|
|
|| policy.mActivePasswordLength < getPasswordMinimumLength(null, userHandle)) {
|
2010-05-24 17:10:56 -07:00
|
|
|
return false;
|
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
if (policy.mActivePasswordQuality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
|
2010-05-24 17:10:56 -07:00
|
|
|
return true;
|
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
return policy.mActivePasswordUpperCase >= getPasswordMinimumUpperCase(null, userHandle)
|
|
|
|
&& policy.mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null, userHandle)
|
|
|
|
&& policy.mActivePasswordLetters >= getPasswordMinimumLetters(null, userHandle)
|
|
|
|
&& policy.mActivePasswordNumeric >= getPasswordMinimumNumeric(null, userHandle)
|
|
|
|
&& policy.mActivePasswordSymbols >= getPasswordMinimumSymbols(null, userHandle)
|
|
|
|
&& policy.mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null, userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public int getCurrentFailedPasswordAttempts(int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
synchronized (this) {
|
|
|
|
// This API can only be called by an active device admin,
|
|
|
|
// so try to retrieve it to check that the caller is one.
|
2010-01-22 11:31:30 -08:00
|
|
|
getActiveAdminForCallerLocked(null,
|
|
|
|
DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
|
2012-09-14 23:20:08 -07:00
|
|
|
return getUserData(userHandle).mFailedPasswordAttempts;
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void setMaximumFailedPasswordsForWipe(ComponentName who, int num, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-26 18:01:04 -08:00
|
|
|
synchronized (this) {
|
|
|
|
// This API can only be called by an active device admin,
|
|
|
|
// so try to retrieve it to check that the caller is one.
|
|
|
|
getActiveAdminForCallerLocked(who,
|
|
|
|
DeviceAdminInfo.USES_POLICY_WIPE_DATA);
|
|
|
|
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
|
|
|
|
DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
|
|
|
|
if (ap.maximumFailedPasswordsForWipe != num) {
|
|
|
|
ap.maximumFailedPasswordsForWipe = num;
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
2010-01-26 18:01:04 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public int getMaximumFailedPasswordsForWipe(ComponentName who, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-26 18:01:04 -08:00
|
|
|
synchronized (this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
2010-01-27 16:21:20 -08:00
|
|
|
int count = 0;
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-27 19:23:59 -08:00
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
|
2010-01-27 19:23:59 -08:00
|
|
|
return admin != null ? admin.maximumFailedPasswordsForWipe : count;
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
final int N = policy.mAdminList.size();
|
2010-01-27 16:21:20 -08:00
|
|
|
for (int i=0; i<N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-01-27 16:21:20 -08:00
|
|
|
if (count == 0) {
|
|
|
|
count = admin.maximumFailedPasswordsForWipe;
|
|
|
|
} else if (admin.maximumFailedPasswordsForWipe != 0
|
|
|
|
&& count > admin.maximumFailedPasswordsForWipe) {
|
|
|
|
count = admin.maximumFailedPasswordsForWipe;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
2010-01-26 18:01:04 -08:00
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public boolean resetPassword(String password, int flags, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-29 10:38:29 -08:00
|
|
|
int quality;
|
2010-01-20 13:37:26 -08:00
|
|
|
synchronized (this) {
|
|
|
|
// This API can only be called by an active device admin,
|
|
|
|
// so try to retrieve it to check that the caller is one.
|
2010-01-22 11:31:30 -08:00
|
|
|
getActiveAdminForCallerLocked(null,
|
|
|
|
DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
|
2012-09-14 23:20:08 -07:00
|
|
|
quality = getPasswordQuality(null, userHandle);
|
2010-01-29 10:38:29 -08:00
|
|
|
if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
|
2010-03-22 11:12:48 -07:00
|
|
|
int realQuality = LockPatternUtils.computePasswordQuality(password);
|
2010-05-24 17:10:56 -07:00
|
|
|
if (realQuality < quality
|
|
|
|
&& quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
|
2010-03-22 11:12:48 -07:00
|
|
|
Slog.w(TAG, "resetPassword: password quality 0x"
|
|
|
|
+ Integer.toHexString(quality)
|
|
|
|
+ " does not meet required quality 0x"
|
|
|
|
+ Integer.toHexString(quality));
|
2010-01-29 10:38:29 -08:00
|
|
|
return false;
|
|
|
|
}
|
2010-05-24 17:10:56 -07:00
|
|
|
quality = Math.max(realQuality, quality);
|
2010-01-29 10:38:29 -08:00
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
int length = getPasswordMinimumLength(null, userHandle);
|
2010-01-29 10:38:29 -08:00
|
|
|
if (password.length() < length) {
|
2010-03-22 11:12:48 -07:00
|
|
|
Slog.w(TAG, "resetPassword: password length " + password.length()
|
|
|
|
+ " does not meet required length " + length);
|
2010-01-20 13:37:26 -08:00
|
|
|
return false;
|
|
|
|
}
|
2010-05-24 17:10:56 -07:00
|
|
|
if (quality == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
|
|
|
|
int letters = 0;
|
|
|
|
int uppercase = 0;
|
|
|
|
int lowercase = 0;
|
|
|
|
int numbers = 0;
|
|
|
|
int symbols = 0;
|
2010-06-04 17:15:02 -07:00
|
|
|
int nonletter = 0;
|
2010-05-24 17:10:56 -07:00
|
|
|
for (int i = 0; i < password.length(); i++) {
|
|
|
|
char c = password.charAt(i);
|
|
|
|
if (c >= 'A' && c <= 'Z') {
|
|
|
|
letters++;
|
|
|
|
uppercase++;
|
|
|
|
} else if (c >= 'a' && c <= 'z') {
|
|
|
|
letters++;
|
|
|
|
lowercase++;
|
|
|
|
} else if (c >= '0' && c <= '9') {
|
|
|
|
numbers++;
|
2010-06-04 17:15:02 -07:00
|
|
|
nonletter++;
|
2010-05-24 17:10:56 -07:00
|
|
|
} else {
|
|
|
|
symbols++;
|
2010-06-04 17:15:02 -07:00
|
|
|
nonletter++;
|
2010-05-24 17:10:56 -07:00
|
|
|
}
|
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
int neededLetters = getPasswordMinimumLetters(null, userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
if(letters < neededLetters) {
|
|
|
|
Slog.w(TAG, "resetPassword: number of letters " + letters
|
|
|
|
+ " does not meet required number of letters " + neededLetters);
|
|
|
|
return false;
|
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
int neededNumbers = getPasswordMinimumNumeric(null, userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
if (numbers < neededNumbers) {
|
|
|
|
Slog
|
|
|
|
.w(TAG, "resetPassword: number of numerical digits " + numbers
|
|
|
|
+ " does not meet required number of numerical digits "
|
|
|
|
+ neededNumbers);
|
|
|
|
return false;
|
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
int neededLowerCase = getPasswordMinimumLowerCase(null, userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
if (lowercase < neededLowerCase) {
|
|
|
|
Slog.w(TAG, "resetPassword: number of lowercase letters " + lowercase
|
|
|
|
+ " does not meet required number of lowercase letters "
|
|
|
|
+ neededLowerCase);
|
|
|
|
return false;
|
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
int neededUpperCase = getPasswordMinimumUpperCase(null, userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
if (uppercase < neededUpperCase) {
|
|
|
|
Slog.w(TAG, "resetPassword: number of uppercase letters " + uppercase
|
|
|
|
+ " does not meet required number of uppercase letters "
|
|
|
|
+ neededUpperCase);
|
|
|
|
return false;
|
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
int neededSymbols = getPasswordMinimumSymbols(null, userHandle);
|
2010-05-24 17:10:56 -07:00
|
|
|
if (symbols < neededSymbols) {
|
|
|
|
Slog.w(TAG, "resetPassword: number of special symbols " + symbols
|
|
|
|
+ " does not meet required number of special symbols " + neededSymbols);
|
|
|
|
return false;
|
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
int neededNonLetter = getPasswordMinimumNonLetter(null, userHandle);
|
2010-06-04 17:15:02 -07:00
|
|
|
if (nonletter < neededNonLetter) {
|
|
|
|
Slog.w(TAG, "resetPassword: number of non-letter characters " + nonletter
|
|
|
|
+ " does not meet required number of non-letter characters "
|
|
|
|
+ neededNonLetter);
|
|
|
|
return false;
|
|
|
|
}
|
2010-05-24 17:10:56 -07:00
|
|
|
}
|
2010-01-20 13:37:26 -08:00
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-02-26 17:25:54 -08:00
|
|
|
int callingUid = Binder.getCallingUid();
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
if (policy.mPasswordOwner >= 0 && policy.mPasswordOwner != callingUid) {
|
2010-03-22 11:12:48 -07:00
|
|
|
Slog.w(TAG, "resetPassword: already set by another uid and not entered by user");
|
2010-02-26 17:25:54 -08:00
|
|
|
return false;
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-20 13:37:26 -08:00
|
|
|
// Don't do this with the lock held, because it is going to call
|
|
|
|
// back in to the service.
|
|
|
|
long ident = Binder.clearCallingIdentity();
|
|
|
|
try {
|
|
|
|
LockPatternUtils utils = new LockPatternUtils(mContext);
|
2012-09-14 23:20:08 -07:00
|
|
|
utils.saveLockPassword(password, quality, false, userHandle);
|
2010-03-22 11:12:48 -07:00
|
|
|
synchronized (this) {
|
|
|
|
int newOwner = (flags&DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY)
|
|
|
|
!= 0 ? callingUid : -1;
|
2012-09-14 23:20:08 -07:00
|
|
|
if (policy.mPasswordOwner != newOwner) {
|
|
|
|
policy.mPasswordOwner = newOwner;
|
|
|
|
saveSettingsLocked(userHandle);
|
2010-03-22 11:12:48 -07:00
|
|
|
}
|
2010-02-26 17:25:54 -08:00
|
|
|
}
|
2010-01-20 13:37:26 -08:00
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(ident);
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-20 13:37:26 -08:00
|
|
|
return true;
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void setMaximumTimeToLock(ComponentName who, long timeMs, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
synchronized (this) {
|
|
|
|
if (who == null) {
|
|
|
|
throw new NullPointerException("ComponentName is null");
|
|
|
|
}
|
2010-01-22 11:31:30 -08:00
|
|
|
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
|
2010-02-11 12:14:08 -08:00
|
|
|
DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
|
2010-01-12 18:14:19 -08:00
|
|
|
if (ap.maximumTimeToUnlock != timeMs) {
|
|
|
|
ap.maximumTimeToUnlock = timeMs;
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
|
|
|
updateMaximumTimeToLockLocked(getUserData(userHandle));
|
2012-06-15 17:05:25 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
void updateMaximumTimeToLockLocked(DevicePolicyData policy) {
|
|
|
|
long timeMs = getMaximumTimeToLock(null, policy.mUserHandle);
|
|
|
|
if (policy.mLastMaximumTimeToLock == timeMs) {
|
2012-06-15 17:05:25 -07:00
|
|
|
return;
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-06-15 17:05:25 -07:00
|
|
|
long ident = Binder.clearCallingIdentity();
|
|
|
|
try {
|
|
|
|
if (timeMs <= 0) {
|
|
|
|
timeMs = Integer.MAX_VALUE;
|
|
|
|
} else {
|
|
|
|
// Make sure KEEP_SCREEN_ON is disabled, since that
|
|
|
|
// would allow bypassing of the maximum time to lock.
|
2012-09-07 15:00:54 -07:00
|
|
|
Settings.Global.putInt(mContext.getContentResolver(),
|
|
|
|
Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
|
2012-06-15 17:05:25 -07:00
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mLastMaximumTimeToLock = timeMs;
|
2012-06-15 17:05:25 -07:00
|
|
|
|
|
|
|
try {
|
Power manager rewrite.
The major goal of this rewrite is to make it easier to implement
power management policies correctly. According, the new
implementation primarily uses state-based rather than event-based
triggers for applying changes to the current power state.
For example, when an application requests that the proximity
sensor be used to manage the screen state (by way of a wake lock),
the power manager makes note of the fact that the set of
wake locks changed. Then it executes a common update function
that recalculates the entire state, first looking at wake locks,
then considering user activity, and eventually determining whether
the screen should be turned on or off. At this point it may
make a request to a component called the DisplayPowerController
to asynchronously update the display's powe state. Likewise,
DisplayPowerController makes note of the updated power request
and schedules its own update function to figure out what needs
to be changed.
The big benefit of this approach is that it's easy to mutate
multiple properties of the power state simultaneously then
apply their joint effects together all at once. Transitions
between states are detected and resolved by the update in
a consistent manner.
The new power manager service has is implemented as a set of
loosely coupled components. For the most part, information
only flows one way through these components (by issuing a
request to that component) although some components support
sending a message back to indicate when the work has been
completed. For example, the DisplayPowerController posts
a callback runnable asynchronously to tell the PowerManagerService
when the display is ready. An important feature of this
approach is that each component neatly encapsulates its
state and maintains its own invariants. Moreover, we do
not need to worry about deadlocks or awkward mutual exclusion
semantics because most of the requests are asynchronous.
The benefits of this design are especially apparent in
the implementation of the screen on / off and brightness
control animations which are able to take advantage of
framework features like properties, ObjectAnimator
and Choreographer.
The screen on / off animation is now the responsibility
of the power manager (instead of surface flinger). This change
makes it much easier to ensure that the animation is properly
coordinated with other power state changes and eliminates
the cause of race conditions in the older implementation.
The because of the userActivity() function has been changed
so that it never wakes the device from sleep. This change
removes ambiguity around forcing or disabling user activity
for various purposes. To wake the device, use wakeUp().
To put it to sleep, use goToSleep(). Simple.
The power manager service interface and API has been significantly
simplified and consolidated. Also fixed some inconsistencies
related to how the minimum and maximum screen brightness setting
was presented in brightness control widgets and enforced behind
the scenes.
At present the following features are implemented:
- Wake locks.
- User activity.
- Wake up / go to sleep.
- Power state broadcasts.
- Battery stats and event log notifications.
- Dreams.
- Proximity screen off.
- Animated screen on / off transitions.
- Auto-dimming.
- Auto-brightness control for the screen backlight with
different timeouts for ramping up versus ramping down.
- Auto-on when plugged or unplugged.
- Stay on when plugged.
- Device administration maximum user activity timeout.
- Application controlled brightness via window manager.
The following features are not yet implemented:
- Reduced user activity timeout for the key guard.
- Reduced user activity timeout for the phone application.
- Coordinating screen on barriers with the window manager.
- Preventing auto-rotation during power state changes.
- Auto-brightness adjustment setting (feature was disabled
in previous version of the power manager service pending
an improved UI design so leaving it out for now).
- Interpolated brightness control (a proposed new scheme
for more compactly specifying auto-brightness levels
in config.xml).
- Button / keyboard backlight control.
- Change window manager to associated WorkSource with
KEEP_SCREEN_ON_FLAG wake lock instead of talking
directly to the battery stats service.
- Optionally support animating screen brightness when
turning on/off instead of playing electron beam animation
(config_animateScreenLights).
Change-Id: I1d7a52e98f0449f76d70bf421f6a7f245957d1d7
2012-07-27 15:51:34 -07:00
|
|
|
getIPowerManager().setMaximumScreenOffTimeoutFromDeviceAdmin((int)timeMs);
|
2012-06-15 17:05:25 -07:00
|
|
|
} catch (RemoteException e) {
|
|
|
|
Slog.w(TAG, "Failure talking with power manager", e);
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
2012-06-15 17:05:25 -07:00
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(ident);
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public long getMaximumTimeToLock(ComponentName who, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
synchronized (this) {
|
2010-01-27 16:21:20 -08:00
|
|
|
long time = 0;
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-27 19:23:59 -08:00
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
|
2010-01-27 19:23:59 -08:00
|
|
|
return admin != null ? admin.maximumTimeToUnlock : time;
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
final int N = policy.mAdminList.size();
|
2010-01-27 16:21:20 -08:00
|
|
|
for (int i=0; i<N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-01-27 16:21:20 -08:00
|
|
|
if (time == 0) {
|
|
|
|
time = admin.maximumTimeToUnlock;
|
|
|
|
} else if (admin.maximumTimeToUnlock != 0
|
|
|
|
&& time > admin.maximumTimeToUnlock) {
|
|
|
|
time = admin.maximumTimeToUnlock;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return time;
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-20 13:37:26 -08:00
|
|
|
public void lockNow() {
|
|
|
|
synchronized (this) {
|
|
|
|
// This API can only be called by an active device admin,
|
|
|
|
// so try to retrieve it to check that the caller is one.
|
2010-01-22 11:31:30 -08:00
|
|
|
getActiveAdminForCallerLocked(null,
|
|
|
|
DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
|
2012-09-14 23:20:08 -07:00
|
|
|
lockNowUnchecked();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void lockNowUnchecked() {
|
|
|
|
long ident = Binder.clearCallingIdentity();
|
|
|
|
try {
|
|
|
|
// Power off the display
|
|
|
|
getIPowerManager().goToSleep(SystemClock.uptimeMillis(),
|
|
|
|
PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN);
|
|
|
|
// Ensure the device is locked
|
|
|
|
getWindowManager().lockNow();
|
|
|
|
} catch (RemoteException e) {
|
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(ident);
|
2010-01-20 13:37:26 -08:00
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2011-10-17 17:30:21 -07:00
|
|
|
private boolean isExtStorageEncrypted() {
|
|
|
|
String state = SystemProperties.get("vold.decrypt");
|
|
|
|
return !"".equals(state);
|
|
|
|
}
|
|
|
|
|
2010-01-26 18:01:04 -08:00
|
|
|
void wipeDataLocked(int flags) {
|
2011-10-17 17:30:21 -07:00
|
|
|
// If the SD card is encrypted and non-removable, we have to force a wipe.
|
|
|
|
boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted();
|
|
|
|
boolean wipeExtRequested = (flags&DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0;
|
|
|
|
|
|
|
|
// Note: we can only do the wipe via ExternalStorageFormatter if the volume is not emulated.
|
|
|
|
if ((forceExtWipe || wipeExtRequested) && !Environment.isExternalStorageEmulated()) {
|
2010-10-15 18:45:07 -07:00
|
|
|
Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
|
2012-02-15 19:25:50 +09:00
|
|
|
intent.putExtra(ExternalStorageFormatter.EXTRA_ALWAYS_RESET, true);
|
2010-10-15 18:45:07 -07:00
|
|
|
intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
|
|
|
|
mWakeLock.acquire(10000);
|
|
|
|
mContext.startService(intent);
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
RecoverySystem.rebootWipeUserData(mContext);
|
|
|
|
} catch (IOException e) {
|
|
|
|
Slog.w(TAG, "Failed requesting data wipe", e);
|
|
|
|
}
|
2010-01-26 18:01:04 -08:00
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void wipeData(int flags, final int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
synchronized (this) {
|
|
|
|
// This API can only be called by an active device admin,
|
|
|
|
// so try to retrieve it to check that the caller is one.
|
2010-01-22 11:31:30 -08:00
|
|
|
getActiveAdminForCallerLocked(null,
|
|
|
|
DeviceAdminInfo.USES_POLICY_WIPE_DATA);
|
2010-01-26 18:01:04 -08:00
|
|
|
long ident = Binder.clearCallingIdentity();
|
|
|
|
try {
|
2012-09-14 23:20:08 -07:00
|
|
|
if (userHandle == UserHandle.USER_OWNER) {
|
|
|
|
wipeDataLocked(flags);
|
|
|
|
} else {
|
|
|
|
lockNowUnchecked();
|
|
|
|
mHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
try {
|
|
|
|
ActivityManagerNative.getDefault().switchUser(0);
|
|
|
|
((UserManager) mContext.getSystemService(Context.USER_SERVICE))
|
|
|
|
.removeUser(userHandle);
|
|
|
|
} catch (RemoteException re) {
|
|
|
|
// Shouldn't happen
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2010-01-26 18:01:04 -08:00
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(ident);
|
|
|
|
}
|
2010-01-20 13:37:26 -08:00
|
|
|
}
|
2010-01-26 18:01:04 -08:00
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void getRemoveWarning(ComponentName comp, final RemoteCallback result, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-26 18:01:04 -08:00
|
|
|
mContext.enforceCallingOrSelfPermission(
|
|
|
|
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-26 18:01:04 -08:00
|
|
|
synchronized (this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(comp, userHandle);
|
2010-01-26 18:01:04 -08:00
|
|
|
if (admin == null) {
|
|
|
|
try {
|
|
|
|
result.sendResult(null);
|
|
|
|
} catch (RemoteException e) {
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2010-02-16 20:38:49 -08:00
|
|
|
Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
|
2010-01-26 18:01:04 -08:00
|
|
|
intent.setComponent(admin.info.getComponent());
|
2012-09-14 23:20:08 -07:00
|
|
|
mContext.sendOrderedBroadcastAsUser(intent, new UserHandle(userHandle),
|
2012-08-29 18:32:08 -07:00
|
|
|
null, new BroadcastReceiver() {
|
2010-01-26 18:01:04 -08:00
|
|
|
@Override
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
|
|
|
try {
|
|
|
|
result.sendResult(getResultExtras(false));
|
|
|
|
} catch (RemoteException e) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, null, Activity.RESULT_OK, null, null);
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-05-24 17:10:56 -07:00
|
|
|
public void setActivePasswordState(int quality, int length, int letters, int uppercase,
|
2012-09-14 23:20:08 -07:00
|
|
|
int lowercase, int numbers, int symbols, int nonletter, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
mContext.enforceCallingOrSelfPermission(
|
|
|
|
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData p = getUserData(userHandle);
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-03-22 11:12:48 -07:00
|
|
|
validateQualityConstant(quality);
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-12 18:14:19 -08:00
|
|
|
synchronized (this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
if (p.mActivePasswordQuality != quality || p.mActivePasswordLength != length
|
|
|
|
|| p.mFailedPasswordAttempts != 0 || p.mActivePasswordLetters != letters
|
|
|
|
|| p.mActivePasswordUpperCase != uppercase
|
|
|
|
|| p.mActivePasswordLowerCase != lowercase || p.mActivePasswordNumeric != numbers
|
|
|
|
|| p.mActivePasswordSymbols != symbols || p.mActivePasswordNonLetter != nonletter) {
|
2010-01-12 18:14:19 -08:00
|
|
|
long ident = Binder.clearCallingIdentity();
|
|
|
|
try {
|
2012-09-14 23:20:08 -07:00
|
|
|
p.mActivePasswordQuality = quality;
|
|
|
|
p.mActivePasswordLength = length;
|
|
|
|
p.mActivePasswordLetters = letters;
|
|
|
|
p.mActivePasswordLowerCase = lowercase;
|
|
|
|
p.mActivePasswordUpperCase = uppercase;
|
|
|
|
p.mActivePasswordNumeric = numbers;
|
|
|
|
p.mActivePasswordSymbols = symbols;
|
|
|
|
p.mActivePasswordNonLetter = nonletter;
|
|
|
|
p.mFailedPasswordAttempts = 0;
|
|
|
|
saveSettingsLocked(userHandle);
|
|
|
|
updatePasswordExpirationsLocked(userHandle);
|
|
|
|
setExpirationAlarmCheckLocked(mContext, p);
|
2010-02-16 20:38:49 -08:00
|
|
|
sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
|
2012-09-14 23:20:08 -07:00
|
|
|
DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(ident);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-11-29 17:43:32 -08:00
|
|
|
/**
|
|
|
|
* Called any time the device password is updated. Resets all password expiration clocks.
|
|
|
|
*/
|
2012-09-14 23:20:08 -07:00
|
|
|
private void updatePasswordExpirationsLocked(int userHandle) {
|
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
final int N = policy.mAdminList.size();
|
2010-11-08 16:15:47 -08:00
|
|
|
if (N > 0) {
|
|
|
|
for (int i=0; i<N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2010-11-08 16:15:47 -08:00
|
|
|
if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) {
|
2010-11-29 17:43:32 -08:00
|
|
|
long timeout = admin.passwordExpirationTimeout;
|
|
|
|
long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L;
|
|
|
|
admin.passwordExpirationDate = expiration;
|
2010-11-08 16:15:47 -08:00
|
|
|
}
|
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
2010-11-08 16:15:47 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void reportFailedPasswordAttempt(int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
mContext.enforceCallingOrSelfPermission(
|
|
|
|
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-12 18:14:19 -08:00
|
|
|
synchronized (this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
long ident = Binder.clearCallingIdentity();
|
|
|
|
try {
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mFailedPasswordAttempts++;
|
|
|
|
saveSettingsLocked(userHandle);
|
|
|
|
int max = getMaximumFailedPasswordsForWipe(null, userHandle);
|
|
|
|
if (max > 0 && policy.mFailedPasswordAttempts >= max) {
|
2010-01-26 18:01:04 -08:00
|
|
|
wipeDataLocked(0);
|
|
|
|
}
|
2010-02-16 20:38:49 -08:00
|
|
|
sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
|
2012-09-14 23:20:08 -07:00
|
|
|
DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(ident);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public void reportSuccessfulPasswordAttempt(int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
mContext.enforceCallingOrSelfPermission(
|
|
|
|
android.Manifest.permission.BIND_DEVICE_ADMIN, null);
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-01-12 18:14:19 -08:00
|
|
|
synchronized (this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
if (policy.mFailedPasswordAttempts != 0 || policy.mPasswordOwner >= 0) {
|
2010-01-12 18:14:19 -08:00
|
|
|
long ident = Binder.clearCallingIdentity();
|
|
|
|
try {
|
2012-09-14 23:20:08 -07:00
|
|
|
policy.mFailedPasswordAttempts = 0;
|
|
|
|
policy.mPasswordOwner = -1;
|
|
|
|
saveSettingsLocked(userHandle);
|
2010-02-16 20:38:49 -08:00
|
|
|
sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
|
2012-09-14 23:20:08 -07:00
|
|
|
DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
|
2010-01-12 18:14:19 -08:00
|
|
|
} finally {
|
|
|
|
Binder.restoreCallingIdentity(ident);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-08-03 10:51:06 -07:00
|
|
|
public ComponentName setGlobalProxy(ComponentName who, String proxySpec,
|
2012-09-14 23:20:08 -07:00
|
|
|
String exclusionList, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-08-03 10:51:06 -07:00
|
|
|
synchronized(this) {
|
|
|
|
if (who == null) {
|
|
|
|
throw new NullPointerException("ComponentName is null");
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
// Only check if owner has set global proxy. We don't allow other users to set it.
|
|
|
|
DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
|
2010-08-03 10:51:06 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminForCallerLocked(who,
|
|
|
|
DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
|
|
|
|
|
|
|
|
// Scan through active admins and find if anyone has already
|
|
|
|
// set the global proxy.
|
2012-09-14 23:20:08 -07:00
|
|
|
Set<ComponentName> compSet = policy.mAdminMap.keySet();
|
2010-08-03 10:51:06 -07:00
|
|
|
for (ComponentName component : compSet) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin ap = policy.mAdminMap.get(component);
|
2010-08-03 10:51:06 -07:00
|
|
|
if ((ap.specifiesGlobalProxy) && (!component.equals(who))) {
|
|
|
|
// Another admin already sets the global proxy
|
|
|
|
// Return it to the caller.
|
|
|
|
return component;
|
|
|
|
}
|
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
|
|
|
|
// If the user is not the owner, don't set the global proxy. Fail silently.
|
|
|
|
if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
|
|
|
|
Slog.w(TAG, "Only the owner is allowed to set the global proxy. User "
|
|
|
|
+ userHandle + " is not permitted.");
|
|
|
|
return null;
|
|
|
|
}
|
2010-08-03 10:51:06 -07:00
|
|
|
if (proxySpec == null) {
|
|
|
|
admin.specifiesGlobalProxy = false;
|
|
|
|
admin.globalProxySpec = null;
|
|
|
|
admin.globalProxyExclusionList = null;
|
|
|
|
} else {
|
|
|
|
|
|
|
|
admin.specifiesGlobalProxy = true;
|
|
|
|
admin.globalProxySpec = proxySpec;
|
|
|
|
admin.globalProxyExclusionList = exclusionList;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset the global proxy accordingly
|
|
|
|
// Do this using system permissions, as apps cannot write to secure settings
|
|
|
|
long origId = Binder.clearCallingIdentity();
|
2012-09-14 23:20:08 -07:00
|
|
|
resetGlobalProxyLocked(policy);
|
2010-08-03 10:51:06 -07:00
|
|
|
Binder.restoreCallingIdentity(origId);
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
public ComponentName getGlobalProxyAdmin(int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2010-08-03 10:51:06 -07:00
|
|
|
synchronized(this) {
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
|
2010-08-03 10:51:06 -07:00
|
|
|
// Scan through active admins and find if anyone has already
|
|
|
|
// set the global proxy.
|
2012-09-14 23:20:08 -07:00
|
|
|
final int N = policy.mAdminList.size();
|
2010-08-03 10:51:06 -07:00
|
|
|
for (int i = 0; i < N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin ap = policy.mAdminList.get(i);
|
2010-08-03 10:51:06 -07:00
|
|
|
if (ap.specifiesGlobalProxy) {
|
|
|
|
// Device admin sets the global proxy
|
|
|
|
// Return it to the caller.
|
|
|
|
return ap.info.getComponent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// No device admin sets the global proxy.
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
private void resetGlobalProxyLocked(DevicePolicyData policy) {
|
|
|
|
final int N = policy.mAdminList.size();
|
2010-08-03 10:51:06 -07:00
|
|
|
for (int i = 0; i < N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin ap = policy.mAdminList.get(i);
|
2010-08-03 10:51:06 -07:00
|
|
|
if (ap.specifiesGlobalProxy) {
|
2012-06-15 17:05:25 -07:00
|
|
|
saveGlobalProxyLocked(ap.globalProxySpec, ap.globalProxyExclusionList);
|
2010-08-03 10:51:06 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// No device admins defining global proxies - reset global proxy settings to none
|
2012-06-15 17:05:25 -07:00
|
|
|
saveGlobalProxyLocked(null, null);
|
2010-08-03 10:51:06 -07:00
|
|
|
}
|
|
|
|
|
2012-06-15 17:05:25 -07:00
|
|
|
private void saveGlobalProxyLocked(String proxySpec, String exclusionList) {
|
2010-08-03 10:51:06 -07:00
|
|
|
if (exclusionList == null) {
|
|
|
|
exclusionList = "";
|
|
|
|
}
|
|
|
|
if (proxySpec == null) {
|
|
|
|
proxySpec = "";
|
|
|
|
}
|
|
|
|
// Remove white spaces
|
|
|
|
proxySpec = proxySpec.trim();
|
2010-10-11 16:00:27 -07:00
|
|
|
String data[] = proxySpec.split(":");
|
|
|
|
int proxyPort = 8080;
|
|
|
|
if (data.length > 1) {
|
|
|
|
try {
|
|
|
|
proxyPort = Integer.parseInt(data[1]);
|
|
|
|
} catch (NumberFormatException e) {}
|
|
|
|
}
|
2010-08-03 10:51:06 -07:00
|
|
|
exclusionList = exclusionList.trim();
|
|
|
|
ContentResolver res = mContext.getContentResolver();
|
2012-09-26 22:03:49 -07:00
|
|
|
Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, data[0]);
|
|
|
|
Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, proxyPort);
|
|
|
|
Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
|
2010-10-11 16:00:27 -07:00
|
|
|
exclusionList);
|
2010-08-03 10:51:06 -07:00
|
|
|
}
|
|
|
|
|
2011-01-12 14:59:52 -08:00
|
|
|
/**
|
2011-01-17 12:47:31 -08:00
|
|
|
* Set the storage encryption request for a single admin. Returns the new total request
|
|
|
|
* status (for all admins).
|
2011-01-12 14:59:52 -08:00
|
|
|
*/
|
2012-09-14 23:20:08 -07:00
|
|
|
public int setStorageEncryption(ComponentName who, boolean encrypt, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2011-01-12 14:59:52 -08:00
|
|
|
synchronized (this) {
|
|
|
|
// Check for permissions
|
|
|
|
if (who == null) {
|
|
|
|
throw new NullPointerException("ComponentName is null");
|
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
// Only owner can set storage encryption
|
|
|
|
if (userHandle != UserHandle.USER_OWNER
|
|
|
|
|| UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
|
|
|
|
Slog.w(TAG, "Only owner is allowed to set storage encryption. User "
|
|
|
|
+ UserHandle.getCallingUserId() + " is not permitted.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-01-12 14:59:52 -08:00
|
|
|
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
|
|
|
|
DeviceAdminInfo.USES_ENCRYPTED_STORAGE);
|
|
|
|
|
2011-01-17 12:47:31 -08:00
|
|
|
// Quick exit: If the filesystem does not support encryption, we can exit early.
|
|
|
|
if (!isEncryptionSupported()) {
|
|
|
|
return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
// (1) Record the value for the admin so it's sticky
|
|
|
|
if (ap.encryptionRequested != encrypt) {
|
|
|
|
ap.encryptionRequested = encrypt;
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
2011-01-17 12:47:31 -08:00
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
|
2011-01-17 12:47:31 -08:00
|
|
|
// (2) Compute "max" for all admins
|
|
|
|
boolean newRequested = false;
|
2012-09-14 23:20:08 -07:00
|
|
|
final int N = policy.mAdminList.size();
|
2011-01-17 12:47:31 -08:00
|
|
|
for (int i = 0; i < N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
newRequested |= policy.mAdminList.get(i).encryptionRequested;
|
2011-01-17 12:47:31 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Notify OS of new request
|
|
|
|
setEncryptionRequested(newRequested);
|
|
|
|
|
|
|
|
// Return the new global request status
|
|
|
|
return newRequested
|
|
|
|
? DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE
|
|
|
|
: DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
|
2011-01-12 14:59:52 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2011-01-17 12:47:31 -08:00
|
|
|
* Get the current storage encryption request status for a given admin, or aggregate of all
|
|
|
|
* active admins.
|
2011-01-12 14:59:52 -08:00
|
|
|
*/
|
2012-09-14 23:20:08 -07:00
|
|
|
public boolean getStorageEncryption(ComponentName who, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2011-01-12 14:59:52 -08:00
|
|
|
synchronized (this) {
|
|
|
|
// Check for permissions if a particular caller is specified
|
|
|
|
if (who != null) {
|
2011-01-17 12:47:31 -08:00
|
|
|
// When checking for a single caller, status is based on caller's request
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin ap = getActiveAdminUncheckedLocked(who, userHandle);
|
2011-06-01 15:30:54 -07:00
|
|
|
return ap != null ? ap.encryptionRequested : false;
|
2011-01-12 14:59:52 -08:00
|
|
|
}
|
|
|
|
|
2011-01-17 12:47:31 -08:00
|
|
|
// If no particular caller is specified, return the aggregate set of requests.
|
|
|
|
// This is short circuited by returning true on the first hit.
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
final int N = policy.mAdminList.size();
|
2011-01-17 12:47:31 -08:00
|
|
|
for (int i = 0; i < N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
if (policy.mAdminList.get(i).encryptionRequested) {
|
2011-01-17 12:47:31 -08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2011-01-12 14:59:52 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-17 12:47:31 -08:00
|
|
|
/**
|
|
|
|
* Get the current encryption status of the device.
|
|
|
|
*/
|
2012-09-14 23:20:08 -07:00
|
|
|
public int getStorageEncryptionStatus(int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2011-01-17 12:47:31 -08:00
|
|
|
return getEncryptionStatus();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hook to low-levels: This should report if the filesystem supports encrypted storage.
|
|
|
|
*/
|
|
|
|
private boolean isEncryptionSupported() {
|
|
|
|
// Note, this can be implemented as
|
|
|
|
// return getEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
|
|
|
|
// But is provided as a separate internal method if there's a faster way to do a
|
|
|
|
// simple check for supported-or-not.
|
|
|
|
return getEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hook to low-levels: Reporting the current status of encryption.
|
|
|
|
* @return A value such as {@link DevicePolicyManager#ENCRYPTION_STATUS_UNSUPPORTED} or
|
|
|
|
* {@link DevicePolicyManager#ENCRYPTION_STATUS_INACTIVE} or
|
|
|
|
* {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE}.
|
|
|
|
*/
|
|
|
|
private int getEncryptionStatus() {
|
2011-01-20 16:35:09 -08:00
|
|
|
String status = SystemProperties.get("ro.crypto.state", "unsupported");
|
|
|
|
if ("encrypted".equalsIgnoreCase(status)) {
|
|
|
|
return DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE;
|
|
|
|
} else if ("unencrypted".equalsIgnoreCase(status)) {
|
|
|
|
return DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
|
|
|
|
} else {
|
|
|
|
return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
|
|
|
|
}
|
2011-01-17 12:47:31 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hook to low-levels: If needed, record the new admin setting for encryption.
|
|
|
|
*/
|
|
|
|
private void setEncryptionRequested(boolean encrypt) {
|
|
|
|
}
|
|
|
|
|
2011-05-09 16:05:33 -07:00
|
|
|
/**
|
|
|
|
* The system property used to share the state of the camera. The native camera service
|
|
|
|
* is expected to read this property and act accordingly.
|
|
|
|
*/
|
|
|
|
public static final String SYSTEM_PROP_DISABLE_CAMERA = "sys.secpolicy.camera.disabled";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Disables all device cameras according to the specified admin.
|
|
|
|
*/
|
2012-09-14 23:20:08 -07:00
|
|
|
public void setCameraDisabled(ComponentName who, boolean disabled, int userHandle) {
|
|
|
|
enforceCrossUserPermission(userHandle);
|
2011-05-09 16:05:33 -07:00
|
|
|
synchronized (this) {
|
|
|
|
if (who == null) {
|
|
|
|
throw new NullPointerException("ComponentName is null");
|
|
|
|
}
|
|
|
|
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
|
|
|
|
DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA);
|
|
|
|
if (ap.disableCamera != disabled) {
|
|
|
|
ap.disableCamera = disabled;
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
2011-05-09 16:05:33 -07:00
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
syncDeviceCapabilitiesLocked(getUserData(userHandle));
|
2011-05-09 16:05:33 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets whether or not all device cameras are disabled for a given admin, or disabled for any
|
|
|
|
* active admins.
|
|
|
|
*/
|
2012-09-14 23:20:08 -07:00
|
|
|
public boolean getCameraDisabled(ComponentName who, int userHandle) {
|
2011-05-09 16:05:33 -07:00
|
|
|
synchronized (this) {
|
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
|
2011-05-09 16:05:33 -07:00
|
|
|
return (admin != null) ? admin.disableCamera : false;
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
2011-05-09 16:05:33 -07:00
|
|
|
// Determine whether or not the device camera is disabled for any active admins.
|
2012-09-14 23:20:08 -07:00
|
|
|
final int N = policy.mAdminList.size();
|
2011-05-09 16:05:33 -07:00
|
|
|
for (int i = 0; i < N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2011-05-09 16:05:33 -07:00
|
|
|
if (admin.disableCamera) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-31 17:19:10 -07:00
|
|
|
/**
|
2012-09-19 23:16:50 -07:00
|
|
|
* Selectively disable keyguard features.
|
2012-08-31 17:19:10 -07:00
|
|
|
*/
|
2012-09-19 23:16:50 -07:00
|
|
|
public void setKeyguardDisabledFeatures(ComponentName who, int which, int userHandle) {
|
2012-09-14 23:20:08 -07:00
|
|
|
enforceCrossUserPermission(userHandle);
|
2012-08-31 17:19:10 -07:00
|
|
|
synchronized (this) {
|
|
|
|
if (who == null) {
|
|
|
|
throw new NullPointerException("ComponentName is null");
|
|
|
|
}
|
|
|
|
ActiveAdmin ap = getActiveAdminForCallerLocked(who,
|
2012-09-19 23:16:50 -07:00
|
|
|
DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
|
|
|
|
if (ap.disabledKeyguardFeatures != which) {
|
|
|
|
ap.disabledKeyguardFeatures = which;
|
2012-09-14 23:20:08 -07:00
|
|
|
saveSettingsLocked(userHandle);
|
2012-08-31 17:19:10 -07:00
|
|
|
}
|
2012-09-14 23:20:08 -07:00
|
|
|
syncDeviceCapabilitiesLocked(getUserData(userHandle));
|
2012-08-31 17:19:10 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2012-09-19 23:16:50 -07:00
|
|
|
* Gets the disabled state for features in keyguard for the given admin,
|
2012-08-31 17:19:10 -07:00
|
|
|
* or the aggregate of all active admins if who is null.
|
|
|
|
*/
|
2012-09-19 23:16:50 -07:00
|
|
|
public int getKeyguardDisabledFeatures(ComponentName who, int userHandle) {
|
2012-09-14 23:20:08 -07:00
|
|
|
enforceCrossUserPermission(userHandle);
|
2012-08-31 17:19:10 -07:00
|
|
|
synchronized (this) {
|
|
|
|
if (who != null) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
|
2012-09-19 23:16:50 -07:00
|
|
|
return (admin != null) ? admin.disabledKeyguardFeatures : 0;
|
2012-08-31 17:19:10 -07:00
|
|
|
}
|
|
|
|
|
2012-09-19 23:16:50 -07:00
|
|
|
// Determine which keyguard features are disabled for any active admins.
|
2012-09-14 23:20:08 -07:00
|
|
|
DevicePolicyData policy = getUserData(userHandle);
|
|
|
|
final int N = policy.mAdminList.size();
|
2012-08-31 17:19:10 -07:00
|
|
|
int which = 0;
|
|
|
|
for (int i = 0; i < N; i++) {
|
2012-09-14 23:20:08 -07:00
|
|
|
ActiveAdmin admin = policy.mAdminList.get(i);
|
2012-09-19 23:16:50 -07:00
|
|
|
which |= admin.disabledKeyguardFeatures;
|
2012-08-31 17:19:10 -07:00
|
|
|
}
|
|
|
|
return which;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
private void enforceCrossUserPermission(int userHandle) {
|
|
|
|
if (userHandle < 0) {
|
|
|
|
throw new IllegalArgumentException("Invalid userId " + userHandle);
|
|
|
|
}
|
|
|
|
final int callingUid = Binder.getCallingUid();
|
|
|
|
if (userHandle == UserHandle.getUserId(callingUid)) return;
|
|
|
|
if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
|
|
|
|
mContext.enforceCallingOrSelfPermission(
|
|
|
|
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "Must be system or have"
|
|
|
|
+ " INTERACT_ACROSS_USERS_FULL permission");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-26 17:25:54 -08:00
|
|
|
@Override
|
|
|
|
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
|
|
|
|
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
|
|
|
|
!= PackageManager.PERMISSION_GRANTED) {
|
|
|
|
|
|
|
|
pw.println("Permission Denial: can't dump DevicePolicyManagerService from from pid="
|
|
|
|
+ Binder.getCallingPid()
|
|
|
|
+ ", uid=" + Binder.getCallingUid());
|
|
|
|
return;
|
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-02-26 17:25:54 -08:00
|
|
|
final Printer p = new PrintWriterPrinter(pw);
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2010-02-26 17:25:54 -08:00
|
|
|
synchronized (this) {
|
|
|
|
p.println("Current Device Policy Manager state:");
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
int userCount = mUserData.size();
|
|
|
|
for (int u = 0; u < userCount; u++) {
|
|
|
|
DevicePolicyData policy = getUserData(mUserData.keyAt(u));
|
|
|
|
p.println(" Enabled Device Admins (User " + policy.mUserHandle + "):");
|
|
|
|
final int N = policy.mAdminList.size();
|
|
|
|
for (int i=0; i<N; i++) {
|
|
|
|
ActiveAdmin ap = policy.mAdminList.get(i);
|
|
|
|
if (ap != null) {
|
|
|
|
pw.print(" "); pw.print(ap.info.getComponent().flattenToShortString());
|
|
|
|
pw.println(":");
|
|
|
|
ap.dump(" ", pw);
|
|
|
|
}
|
2010-02-26 17:25:54 -08:00
|
|
|
}
|
2010-05-20 16:18:05 -07:00
|
|
|
|
2012-09-14 23:20:08 -07:00
|
|
|
pw.println(" ");
|
|
|
|
pw.print(" mPasswordOwner="); pw.println(policy.mPasswordOwner);
|
|
|
|
}
|
2010-02-26 17:25:54 -08:00
|
|
|
}
|
|
|
|
}
|
2010-01-12 18:14:19 -08:00
|
|
|
}
|