blob: fe0abe63820742fd110e03cb544993979ec0ae40 [file] [log] [blame]
Dianne Hackbornd6847842010-01-12 18:14:19 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Amith Yamasani30f8eb42013-11-06 14:54:50 -080017package com.android.server.devicepolicy;
Dianne Hackbornd6847842010-01-12 18:14:19 -080018
Maggie Benthallda51e682013-08-08 22:35:44 -040019import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
Paul Crowleya7e87ac2014-11-18 13:50:19 +000020import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
21import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
Jessica Hummeldd31a102014-09-16 11:56:50 +010022import static android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES;
Maggie Benthallda51e682013-08-08 22:35:44 -040023
Kenny Guyfa80a4f2014-08-20 19:40:59 +010024import android.accessibilityservice.AccessibilityServiceInfo;
Esteban Talaverab5ef1622014-09-08 17:49:01 +010025import android.accounts.AccountManager;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080026import android.app.Activity;
Sudheer Shanka6c780ac2016-06-08 17:13:24 -070027import android.app.ActivityManager;
Amith Yamasani599dd7c2012-09-14 23:20:08 -070028import android.app.ActivityManagerNative;
Jim Millera4e28d12010-11-08 16:15:47 -080029import android.app.AlarmManager;
Amith Yamasani599dd7c2012-09-14 23:20:08 -070030import android.app.AppGlobals;
Jason Monk03978a42014-06-10 15:05:30 -040031import android.app.IActivityManager;
Maggie Benthall0469f412013-09-05 15:30:26 -040032import android.app.Notification;
33import android.app.NotificationManager;
Jim Millera4e28d12010-11-08 16:15:47 -080034import android.app.PendingIntent;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080035import android.app.admin.DeviceAdminInfo;
36import android.app.admin.DeviceAdminReceiver;
37import android.app.admin.DevicePolicyManager;
Julia Reynolds2cb384f2014-08-13 15:15:55 -040038import android.app.admin.DevicePolicyManagerInternal;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080039import android.app.admin.IDevicePolicyManager;
Zoltan Szatmary-Ban26ac6a62014-11-13 20:49:43 +000040import android.app.backup.IBackupManager;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080041import android.content.BroadcastReceiver;
Dianne Hackbornd6847842010-01-12 18:14:19 -080042import android.content.ComponentName;
Oscar Montemayor69238c62010-08-03 10:51:06 -070043import android.content.ContentResolver;
Dianne Hackbornd6847842010-01-12 18:14:19 -080044import android.content.Context;
45import android.content.Intent;
Jim Millera4e28d12010-11-08 16:15:47 -080046import android.content.IntentFilter;
Amith Yamasani71e6c692013-03-24 17:39:28 -070047import android.content.pm.ApplicationInfo;
Amith Yamasani599dd7c2012-09-14 23:20:08 -070048import android.content.pm.IPackageManager;
Dianne Hackbornd6847842010-01-12 18:14:19 -080049import android.content.pm.PackageManager;
Kenny Guyfa80a4f2014-08-20 19:40:59 +010050import android.content.pm.PackageManager.NameNotFoundException;
Andy Stadler1f35d482010-11-19 15:39:41 -080051import android.content.pm.ResolveInfo;
Maggie Benthall0469f412013-09-05 15:30:26 -040052import android.content.pm.UserInfo;
Bernhard Bauer26408cc2014-09-08 14:07:31 +010053import android.database.ContentObserver;
54import android.hardware.usb.UsbManager;
Julia Reynolds4a21b252014-06-04 11:11:43 -040055import android.media.AudioManager;
56import android.media.IAudioService;
Jason Monk03bc9912014-05-13 09:44:57 -040057import android.net.ConnectivityManager;
Jason Monk54a9ebb2014-05-07 15:26:22 -040058import android.net.ProxyInfo;
Bernhard Bauer26408cc2014-09-08 14:07:31 +010059import android.net.Uri;
Robin Leed0130e82014-10-06 11:36:25 +010060import android.os.AsyncTask;
Dianne Hackbornd6847842010-01-12 18:14:19 -080061import android.os.Binder;
Robin Lee66e5d962014-04-09 16:44:21 +010062import android.os.Bundle;
Ben Komaloed48c8b2011-10-17 17:30:21 -070063import android.os.Environment;
Kenny Guy212037f2015-01-15 18:14:46 +000064import android.os.FileUtils;
Jim Millera4e28d12010-11-08 16:15:47 -080065import android.os.Handler;
Dianne Hackborndf83afa2010-01-20 13:37:26 -080066import android.os.IBinder;
Jim Millere303bf42014-08-26 17:12:29 -070067import android.os.PersistableBundle;
Dianne Hackborn42499172010-10-15 18:45:07 -070068import android.os.PowerManager;
Jeff Brown5ce1cb22014-11-06 19:05:33 -080069import android.os.PowerManagerInternal;
Amith Yamasani599dd7c2012-09-14 23:20:08 -070070import android.os.Process;
Dianne Hackborndf83afa2010-01-20 13:37:26 -080071import android.os.RecoverySystem;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -080072import android.os.RemoteCallback;
Dianne Hackborndf83afa2010-01-20 13:37:26 -080073import android.os.RemoteException;
74import android.os.ServiceManager;
Dianne Hackborn254cb442010-01-27 19:23:59 -080075import android.os.SystemClock;
Andy Stadler0fe45de2011-01-20 16:35:09 -080076import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070077import android.os.UserHandle;
Amith Yamasani599dd7c2012-09-14 23:20:08 -070078import android.os.UserManager;
Oscar Montemayor69238c62010-08-03 10:51:06 -070079import android.provider.Settings;
Maggie Benthallda51e682013-08-08 22:35:44 -040080import android.security.Credentials;
Bernhard Bauer26408cc2014-09-08 14:07:31 +010081import android.security.IKeyChainService;
Maggie Benthallda51e682013-08-08 22:35:44 -040082import android.security.KeyChain;
83import android.security.KeyChain.KeyChainConnection;
Adrian Roosf8f56bc2014-11-20 23:55:34 +010084import android.text.TextUtils;
Paul Crowleya7e87ac2014-11-18 13:50:19 +000085import android.service.persistentdata.PersistentDataBlockManager;
Maggie Benthallda51e682013-08-08 22:35:44 -040086import android.util.Log;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -080087import android.util.PrintWriterPrinter;
88import android.util.Printer;
Andy Stadler1f35d482010-11-19 15:39:41 -080089import android.util.Slog;
Amith Yamasani599dd7c2012-09-14 23:20:08 -070090import android.util.SparseArray;
Dianne Hackbornd6847842010-01-12 18:14:19 -080091import android.util.Xml;
Kenny Guyfa80a4f2014-08-20 19:40:59 +010092import android.view.accessibility.AccessibilityManager;
93import android.view.accessibility.IAccessibilityManager;
94import android.view.inputmethod.InputMethodInfo;
95import android.view.inputmethod.InputMethodManager;
Jim Miller93c518e2012-01-17 15:55:31 -080096import android.view.IWindowManager;
Dianne Hackbornd6847842010-01-12 18:14:19 -080097
Julia Reynolds2cb384f2014-08-13 15:15:55 -040098import com.android.internal.R;
99import com.android.internal.os.storage.ExternalStorageFormatter;
100import com.android.internal.util.FastXmlSerializer;
101import com.android.internal.util.JournaledFile;
102import com.android.internal.util.XmlUtils;
103import com.android.internal.widget.LockPatternUtils;
Julia Reynolds2cb384f2014-08-13 15:15:55 -0400104import com.android.server.LocalServices;
105import com.android.server.SystemService;
Jim Millere303bf42014-08-26 17:12:29 -0700106import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
Julia Reynolds2cb384f2014-08-13 15:15:55 -0400107
Adam Connors776c5552014-01-09 10:42:56 +0000108import org.xmlpull.v1.XmlPullParser;
Jim Miller604e7552014-07-18 19:00:02 -0700109
110import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
111import static org.xmlpull.v1.XmlPullParser.END_TAG;
112import static org.xmlpull.v1.XmlPullParser.TEXT;
113
Adam Connors776c5552014-01-09 10:42:56 +0000114import org.xmlpull.v1.XmlPullParserException;
115import org.xmlpull.v1.XmlSerializer;
116
Maggie Benthallda51e682013-08-08 22:35:44 -0400117import java.io.ByteArrayInputStream;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800118import java.io.File;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800119import java.io.FileDescriptor;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800120import java.io.FileInputStream;
Dianne Hackborncef65ee2010-09-30 18:27:22 -0700121import java.io.FileNotFoundException;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800122import java.io.FileOutputStream;
123import java.io.IOException;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800124import java.io.PrintWriter;
Maggie Benthallda51e682013-08-08 22:35:44 -0400125import java.security.cert.CertificateException;
126import java.security.cert.CertificateFactory;
127import java.security.cert.X509Certificate;
Jim Millera4e28d12010-11-08 16:15:47 -0800128import java.text.DateFormat;
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800129import java.util.ArrayList;
Amith Yamasani44a01b72013-09-16 10:44:57 -0700130import java.util.Collections;
Jim Millera4e28d12010-11-08 16:15:47 -0800131import java.util.Date;
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -0800132import java.util.HashMap;
Sander Alewijnse5c02db62014-05-07 10:46:57 +0100133import java.util.HashSet;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800134import java.util.List;
Jim Miller604e7552014-07-18 19:00:02 -0700135import java.util.Map.Entry;
Oscar Montemayor69238c62010-08-03 10:51:06 -0700136import java.util.Set;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800137
138/**
139 * Implementation of the device policy APIs.
140 */
141public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700142
Amith Yamasanief38a102013-12-13 09:05:26 -0800143 private static final String LOG_TAG = "DevicePolicyManagerService";
Jim Millera4e28d12010-11-08 16:15:47 -0800144
Amith Yamasani71e6c692013-03-24 17:39:28 -0700145 private static final String DEVICE_POLICIES_XML = "device_policies.xml";
146
justinzhang511e0d82014-03-24 16:09:24 -0400147 private static final String LOCK_TASK_COMPONENTS_XML = "lock-task-component";
148
Jim Miller6b857682011-02-16 16:27:41 -0800149 private static final int REQUEST_EXPIRE_PASSWORD = 5571;
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700150
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700151 private static final long MS_PER_DAY = 86400 * 1000;
152
153 private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * MS_PER_DAY; // 5 days, in ms
Jim Millera4e28d12010-11-08 16:15:47 -0800154
155 protected static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION
156 = "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION";
157
Maggie Benthall0469f412013-09-05 15:30:26 -0400158 private static final int MONITORING_CERT_NOTIFICATION_ID = R.string.ssl_ca_cert_warning;
159
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700160 private static final boolean DBG = false;
Jim Millera4e28d12010-11-08 16:15:47 -0800161
Amith Yamasanif20d6402014-05-24 15:34:37 -0700162 private static final String ATTR_PERMISSION_PROVIDER = "permission-provider";
Amith Yamasanied239cb2014-07-16 17:26:17 -0700163 private static final String ATTR_SETUP_COMPLETE = "setup-complete";
Amith Yamasanif20d6402014-05-24 15:34:37 -0700164
Julia Reynolds2cb384f2014-08-13 15:15:55 -0400165 private static final Set<String> DEVICE_OWNER_USER_RESTRICTIONS;
166 static {
167 DEVICE_OWNER_USER_RESTRICTIONS = new HashSet();
168 DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_USB_FILE_TRANSFER);
169 DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_CONFIG_TETHERING);
170 DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_FACTORY_RESET);
171 DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_ADD_USER);
172 DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS);
173 DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
174 DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA);
175 DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_UNMUTE_MICROPHONE);
176 DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_ADJUST_VOLUME);
177 DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_SMS);
178 }
179
Julia Reynolds9ed66da2014-08-26 15:42:03 -0400180 private static final Set<String> SECURE_SETTINGS_WHITELIST;
Julia Reynolds82735bc2014-09-04 16:43:30 -0400181 private static final Set<String> SECURE_SETTINGS_DEVICEOWNER_WHITELIST;
Julia Reynolds9ed66da2014-08-26 15:42:03 -0400182 private static final Set<String> GLOBAL_SETTINGS_WHITELIST;
183 static {
184 SECURE_SETTINGS_WHITELIST = new HashSet();
185 SECURE_SETTINGS_WHITELIST.add(Settings.Secure.DEFAULT_INPUT_METHOD);
186 SECURE_SETTINGS_WHITELIST.add(Settings.Secure.SKIP_FIRST_USE_HINTS);
Amith Yamasani52c39a12014-10-21 11:14:04 -0700187 SECURE_SETTINGS_WHITELIST.add(Settings.Secure.INSTALL_NON_MARKET_APPS);
Julia Reynolds9ed66da2014-08-26 15:42:03 -0400188
Julia Reynolds82735bc2014-09-04 16:43:30 -0400189 SECURE_SETTINGS_DEVICEOWNER_WHITELIST = new HashSet();
190 SECURE_SETTINGS_DEVICEOWNER_WHITELIST.addAll(SECURE_SETTINGS_WHITELIST);
191 SECURE_SETTINGS_DEVICEOWNER_WHITELIST.add(Settings.Secure.LOCATION_MODE);
192
Julia Reynolds9ed66da2014-08-26 15:42:03 -0400193 GLOBAL_SETTINGS_WHITELIST = new HashSet();
194 GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.ADB_ENABLED);
195 GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.AUTO_TIME);
196 GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.AUTO_TIME_ZONE);
197 GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.BLUETOOTH_ON);
198 GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.DATA_ROAMING);
199 GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.DEVELOPMENT_SETTINGS_ENABLED);
200 GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.MODE_RINGER);
201 GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.NETWORK_PREFERENCE);
202 GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.USB_MASS_STORAGE_ENABLED);
203 GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.WIFI_ON);
204 GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.WIFI_SLEEP_POLICY);
205 }
206
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800207 final Context mContext;
Jessica Hummel91da58d2014-04-10 17:39:43 +0100208 final UserManager mUserManager;
Dianne Hackborn42499172010-10-15 18:45:07 -0700209 final PowerManager.WakeLock mWakeLock;
Dianne Hackbornd6847842010-01-12 18:14:19 -0800210
Svet Ganov6bd70252014-08-20 09:47:47 -0700211 final LocalService mLocalService;
212
Jeff Brown5ce1cb22014-11-06 19:05:33 -0800213 final PowerManager mPowerManager;
214 final PowerManagerInternal mPowerManagerInternal;
215
Jim Miller93c518e2012-01-17 15:55:31 -0800216 IWindowManager mIWindowManager;
Maggie Benthall0469f412013-09-05 15:30:26 -0400217 NotificationManager mNotificationManager;
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700218
Adam Connors776c5552014-01-09 10:42:56 +0000219 // Stores and loads state on device and profile owners.
Amith Yamasani71e6c692013-03-24 17:39:28 -0700220 private DeviceOwner mDeviceOwner;
221
Amith Yamasani44a01b72013-09-16 10:44:57 -0700222 /**
223 * Whether or not device admin feature is supported. If it isn't return defaults for all
224 * public methods.
225 */
226 private boolean mHasFeature;
227
Jeff Brownb880d882014-02-10 19:47:07 -0800228 public static final class Lifecycle extends SystemService {
229 private DevicePolicyManagerService mService;
230
231 public Lifecycle(Context context) {
232 super(context);
233 mService = new DevicePolicyManagerService(context);
234 }
235
236 @Override
237 public void onStart() {
238 publishBinderService(Context.DEVICE_POLICY_SERVICE, mService);
239 }
240
241 @Override
242 public void onBootPhase(int phase) {
243 if (phase == PHASE_LOCK_SETTINGS_READY) {
244 mService.systemReady();
245 }
246 }
247 }
Amith Yamasanied239cb2014-07-16 17:26:17 -0700248
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700249 public static class DevicePolicyData {
250 int mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
251 int mActivePasswordLength = 0;
252 int mActivePasswordUpperCase = 0;
253 int mActivePasswordLowerCase = 0;
254 int mActivePasswordLetters = 0;
255 int mActivePasswordNumeric = 0;
256 int mActivePasswordSymbols = 0;
257 int mActivePasswordNonLetter = 0;
258 int mFailedPasswordAttempts = 0;
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700259
Robin Lee5c921da2014-03-24 15:11:35 +0000260 int mUserHandle;
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700261 int mPasswordOwner = -1;
262 long mLastMaximumTimeToLock = -1;
Amith Yamasanied239cb2014-07-16 17:26:17 -0700263 boolean mUserSetupComplete = false;
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700264
265 final HashMap<ComponentName, ActiveAdmin> mAdminMap
266 = new HashMap<ComponentName, ActiveAdmin>();
267 final ArrayList<ActiveAdmin> mAdminList
268 = new ArrayList<ActiveAdmin>();
Fyodor Kupolov96fb9322014-12-01 15:08:09 -0800269 final ArrayList<ComponentName> mRemovingAdmins
270 = new ArrayList<ComponentName>();
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700271
justinzhang511e0d82014-03-24 16:09:24 -0400272 // This is the list of component allowed to start lock task mode.
Jason Monkd7b86212014-06-16 13:15:38 -0400273 final List<String> mLockTaskPackages = new ArrayList<String>();
justinzhang511e0d82014-03-24 16:09:24 -0400274
Amith Yamasanif20d6402014-05-24 15:34:37 -0700275 ComponentName mRestrictionsProvider;
276
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700277 public DevicePolicyData(int userHandle) {
278 mUserHandle = userHandle;
279 }
280 }
281
282 final SparseArray<DevicePolicyData> mUserData = new SparseArray<DevicePolicyData>();
283
Jim Millera4e28d12010-11-08 16:15:47 -0800284 Handler mHandler = new Handler();
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700285
Jim Millera4e28d12010-11-08 16:15:47 -0800286 BroadcastReceiver mReceiver = new BroadcastReceiver() {
287 @Override
288 public void onReceive(Context context, Intent intent) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700289 final String action = intent.getAction();
290 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
291 getSendingUserId());
Jim Millera4e28d12010-11-08 16:15:47 -0800292 if (Intent.ACTION_BOOT_COMPLETED.equals(action)
293 || ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800294 if (DBG) Slog.v(LOG_TAG, "Sending password expiration notifications for action "
Dianne Hackborn40e9f292012-11-27 19:12:23 -0800295 + action + " for user " + userHandle);
Jim Millera4e28d12010-11-08 16:15:47 -0800296 mHandler.post(new Runnable() {
297 public void run() {
Jessica Hummel91da58d2014-04-10 17:39:43 +0100298 handlePasswordExpirationNotification(userHandle);
Jim Millera4e28d12010-11-08 16:15:47 -0800299 }
300 });
Maggie Benthall0469f412013-09-05 15:30:26 -0400301 }
302 if (Intent.ACTION_BOOT_COMPLETED.equals(action)
303 || KeyChain.ACTION_STORAGE_CHANGED.equals(action)) {
Robin Leed0130e82014-10-06 11:36:25 +0100304 new MonitoringCertNotificationTask().execute(intent);
Maggie Benthall0469f412013-09-05 15:30:26 -0400305 }
306 if (Intent.ACTION_USER_REMOVED.equals(action)) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700307 removeUserData(userHandle);
308 } else if (Intent.ACTION_USER_STARTED.equals(action)
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700309 || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
310
311 if (Intent.ACTION_USER_STARTED.equals(action)) {
312 // Reset the policy data
313 synchronized (DevicePolicyManagerService.this) {
314 mUserData.remove(userHandle);
315 }
316 }
Amith Yamasania0116af2014-12-04 14:49:24 -0800317 handlePackagesChanged(null /* check all admins */, userHandle);
318 } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
319 || (Intent.ACTION_PACKAGE_ADDED.equals(action)
320 && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false))) {
321 handlePackagesChanged(intent.getData().getSchemeSpecificPart(), userHandle);
322 } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
323 && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
324 handlePackagesChanged(intent.getData().getSchemeSpecificPart(), userHandle);
Jim Millera4e28d12010-11-08 16:15:47 -0800325 }
326 }
327 };
328
Dianne Hackbornd6847842010-01-12 18:14:19 -0800329 static class ActiveAdmin {
Amith Yamasanief38a102013-12-13 09:05:26 -0800330 private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features";
331 private static final String TAG_DISABLE_CAMERA = "disable-camera";
Adam Connors210fe212014-07-17 15:41:43 +0100332 private static final String TAG_DISABLE_CALLER_ID = "disable-caller-id";
Sander Alewijnsed2a1eec2014-07-09 12:57:05 +0100333 private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture";
Sander Alewijnse5c02db62014-05-07 10:46:57 +0100334 private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management";
Sander Alewijnse0ced6272014-08-26 11:18:26 +0100335 private static final String TAG_REQUIRE_AUTO_TIME = "require_auto_time";
Sander Alewijnse5c02db62014-05-07 10:46:57 +0100336 private static final String TAG_ACCOUNT_TYPE = "account-type";
Kenny Guyfa80a4f2014-08-20 19:40:59 +0100337 private static final String TAG_PERMITTED_ACCESSIBILITY_SERVICES
338 = "permitted-accessiblity-services";
Amith Yamasanief38a102013-12-13 09:05:26 -0800339 private static final String TAG_ENCRYPTION_REQUESTED = "encryption-requested";
Jim Miller604e7552014-07-18 19:00:02 -0700340 private static final String TAG_MANAGE_TRUST_AGENT_FEATURES = "manage-trust-agent-features";
Jim Millere303bf42014-08-26 17:12:29 -0700341 private static final String TAG_TRUST_AGENT_COMPONENT_OPTIONS = "trust-agent-component-options";
Jim Miller604e7552014-07-18 19:00:02 -0700342 private static final String TAG_TRUST_AGENT_COMPONENT = "component";
Amith Yamasanief38a102013-12-13 09:05:26 -0800343 private static final String TAG_PASSWORD_EXPIRATION_DATE = "password-expiration-date";
344 private static final String TAG_PASSWORD_EXPIRATION_TIMEOUT = "password-expiration-timeout";
345 private static final String TAG_GLOBAL_PROXY_EXCLUSION_LIST = "global-proxy-exclusion-list";
346 private static final String TAG_GLOBAL_PROXY_SPEC = "global-proxy-spec";
347 private static final String TAG_SPECIFIES_GLOBAL_PROXY = "specifies-global-proxy";
Kenny Guyfa80a4f2014-08-20 19:40:59 +0100348 private static final String TAG_PERMITTED_IMES = "permitted-imes";
Amith Yamasanief38a102013-12-13 09:05:26 -0800349 private static final String TAG_MAX_FAILED_PASSWORD_WIPE = "max-failed-password-wipe";
350 private static final String TAG_MAX_TIME_TO_UNLOCK = "max-time-to-unlock";
351 private static final String TAG_MIN_PASSWORD_NONLETTER = "min-password-nonletter";
352 private static final String TAG_MIN_PASSWORD_SYMBOLS = "min-password-symbols";
353 private static final String TAG_MIN_PASSWORD_NUMERIC = "min-password-numeric";
354 private static final String TAG_MIN_PASSWORD_LETTERS = "min-password-letters";
355 private static final String TAG_MIN_PASSWORD_LOWERCASE = "min-password-lowercase";
356 private static final String TAG_MIN_PASSWORD_UPPERCASE = "min-password-uppercase";
357 private static final String TAG_PASSWORD_HISTORY_LENGTH = "password-history-length";
358 private static final String TAG_MIN_PASSWORD_LENGTH = "min-password-length";
359 private static final String ATTR_VALUE = "value";
360 private static final String TAG_PASSWORD_QUALITY = "password-quality";
361 private static final String TAG_POLICIES = "policies";
Svetoslav976e8bd2014-07-16 15:12:03 -0700362 private static final String TAG_CROSS_PROFILE_WIDGET_PROVIDERS =
363 "cross-profile-widget-providers";
364 private static final String TAG_PROVIDER = "provider";
Kenny Guyfa80a4f2014-08-20 19:40:59 +0100365 private static final String TAG_PACKAGE_LIST_ITEM = "item";
Amith Yamasanief38a102013-12-13 09:05:26 -0800366
Dianne Hackbornd6847842010-01-12 18:14:19 -0800367 final DeviceAdminInfo info;
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700368
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800369 int passwordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700370
371 static final int DEF_MINIMUM_PASSWORD_LENGTH = 0;
372 int minimumPasswordLength = DEF_MINIMUM_PASSWORD_LENGTH;
373
374 static final int DEF_PASSWORD_HISTORY_LENGTH = 0;
375 int passwordHistoryLength = DEF_PASSWORD_HISTORY_LENGTH;
376
377 static final int DEF_MINIMUM_PASSWORD_UPPER_CASE = 0;
378 int minimumPasswordUpperCase = DEF_MINIMUM_PASSWORD_UPPER_CASE;
379
380 static final int DEF_MINIMUM_PASSWORD_LOWER_CASE = 0;
381 int minimumPasswordLowerCase = DEF_MINIMUM_PASSWORD_LOWER_CASE;
382
xusai57877852015-08-18 17:33:00 +0800383 static final int DEF_MINIMUM_PASSWORD_LETTERS = 0;
Dianne Hackborn2a108402011-05-26 11:45:00 -0700384 int minimumPasswordLetters = DEF_MINIMUM_PASSWORD_LETTERS;
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700385
xusai57877852015-08-18 17:33:00 +0800386 static final int DEF_MINIMUM_PASSWORD_NUMERIC = 0;
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700387 int minimumPasswordNumeric = DEF_MINIMUM_PASSWORD_NUMERIC;
388
xusai57877852015-08-18 17:33:00 +0800389 static final int DEF_MINIMUM_PASSWORD_SYMBOLS = 0;
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700390 int minimumPasswordSymbols = DEF_MINIMUM_PASSWORD_SYMBOLS;
391
392 static final int DEF_MINIMUM_PASSWORD_NON_LETTER = 0;
393 int minimumPasswordNonLetter = DEF_MINIMUM_PASSWORD_NON_LETTER;
394
395 static final long DEF_MAXIMUM_TIME_TO_UNLOCK = 0;
396 long maximumTimeToUnlock = DEF_MAXIMUM_TIME_TO_UNLOCK;
397
398 static final int DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE = 0;
399 int maximumFailedPasswordsForWipe = DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE;
400
401 static final long DEF_PASSWORD_EXPIRATION_TIMEOUT = 0;
402 long passwordExpirationTimeout = DEF_PASSWORD_EXPIRATION_TIMEOUT;
403
404 static final long DEF_PASSWORD_EXPIRATION_DATE = 0;
405 long passwordExpirationDate = DEF_PASSWORD_EXPIRATION_DATE;
406
Jim Miller48b9b0d2012-09-19 23:16:50 -0700407 static final int DEF_KEYGUARD_FEATURES_DISABLED = 0; // none
Jim Millere303bf42014-08-26 17:12:29 -0700408
Jim Miller48b9b0d2012-09-19 23:16:50 -0700409 int disabledKeyguardFeatures = DEF_KEYGUARD_FEATURES_DISABLED;
Jim Millerb8ec4702012-08-31 17:19:10 -0700410
Andy Stadler22dbfda2011-01-17 12:47:31 -0800411 boolean encryptionRequested = false;
Ben Komalo2447edd2011-05-09 16:05:33 -0700412 boolean disableCamera = false;
Adam Connors210fe212014-07-17 15:41:43 +0100413 boolean disableCallerId = false;
Sander Alewijnsed2a1eec2014-07-09 12:57:05 +0100414 boolean disableScreenCapture = false; // Can only be set by a device/profile owner.
Sander Alewijnse0ced6272014-08-26 11:18:26 +0100415 boolean requireAutoTime = false; // Can only be set by a device owner.
Sander Alewijnsed2a1eec2014-07-09 12:57:05 +0100416
Jim Millere303bf42014-08-26 17:12:29 -0700417 static class TrustAgentInfo {
418 public PersistableBundle options;
419 TrustAgentInfo(PersistableBundle bundle) {
420 options = bundle;
421 }
422 }
423
Sander Alewijnse5c02db62014-05-07 10:46:57 +0100424 Set<String> accountTypesWithManagementDisabled = new HashSet<String>();
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700425
Kenny Guyfa80a4f2014-08-20 19:40:59 +0100426 // The list of permitted accessibility services package namesas set by a profile
427 // or device owner. Null means all accessibility services are allowed, empty means
428 // none except system services are allowed.
429 List<String> permittedAccessiblityServices;
430
431 // The list of permitted input methods package names as set by a profile or device owner.
432 // Null means all input methods are allowed, empty means none except system imes are
433 // allowed.
434 List<String> permittedInputMethods;
435
Oscar Montemayor69238c62010-08-03 10:51:06 -0700436 // TODO: review implementation decisions with frameworks team
437 boolean specifiesGlobalProxy = false;
438 String globalProxySpec = null;
439 String globalProxyExclusionList = null;
Jim Millere303bf42014-08-26 17:12:29 -0700440
441 HashMap<String, TrustAgentInfo> trustAgentInfos = new HashMap<String, TrustAgentInfo>();
Oscar Montemayor69238c62010-08-03 10:51:06 -0700442
Svetoslav976e8bd2014-07-16 15:12:03 -0700443 List<String> crossProfileWidgetProviders;
444
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800445 ActiveAdmin(DeviceAdminInfo _info) {
446 info = _info;
447 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700448
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800449 int getUid() { return info.getActivityInfo().applicationInfo.uid; }
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700450
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700451 public UserHandle getUserHandle() {
452 return new UserHandle(UserHandle.getUserId(info.getActivityInfo().applicationInfo.uid));
453 }
454
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800455 void writeToXml(XmlSerializer out)
456 throws IllegalArgumentException, IllegalStateException, IOException {
Amith Yamasanief38a102013-12-13 09:05:26 -0800457 out.startTag(null, TAG_POLICIES);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800458 info.writePoliciesToXml(out);
Amith Yamasanief38a102013-12-13 09:05:26 -0800459 out.endTag(null, TAG_POLICIES);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800460 if (passwordQuality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800461 out.startTag(null, TAG_PASSWORD_QUALITY);
462 out.attribute(null, ATTR_VALUE, Integer.toString(passwordQuality));
463 out.endTag(null, TAG_PASSWORD_QUALITY);
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700464 if (minimumPasswordLength != DEF_MINIMUM_PASSWORD_LENGTH) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800465 out.startTag(null, TAG_MIN_PASSWORD_LENGTH);
466 out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordLength));
467 out.endTag(null, TAG_MIN_PASSWORD_LENGTH);
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700468 }
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700469 if(passwordHistoryLength != DEF_PASSWORD_HISTORY_LENGTH) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800470 out.startTag(null, TAG_PASSWORD_HISTORY_LENGTH);
471 out.attribute(null, ATTR_VALUE, Integer.toString(passwordHistoryLength));
472 out.endTag(null, TAG_PASSWORD_HISTORY_LENGTH);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800473 }
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700474 if (minimumPasswordUpperCase != DEF_MINIMUM_PASSWORD_UPPER_CASE) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800475 out.startTag(null, TAG_MIN_PASSWORD_UPPERCASE);
476 out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordUpperCase));
477 out.endTag(null, TAG_MIN_PASSWORD_UPPERCASE);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700478 }
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700479 if (minimumPasswordLowerCase != DEF_MINIMUM_PASSWORD_LOWER_CASE) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800480 out.startTag(null, TAG_MIN_PASSWORD_LOWERCASE);
481 out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordLowerCase));
482 out.endTag(null, TAG_MIN_PASSWORD_LOWERCASE);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700483 }
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700484 if (minimumPasswordLetters != DEF_MINIMUM_PASSWORD_LETTERS) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800485 out.startTag(null, TAG_MIN_PASSWORD_LETTERS);
486 out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordLetters));
487 out.endTag(null, TAG_MIN_PASSWORD_LETTERS);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700488 }
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700489 if (minimumPasswordNumeric != DEF_MINIMUM_PASSWORD_NUMERIC) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800490 out.startTag(null, TAG_MIN_PASSWORD_NUMERIC);
491 out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordNumeric));
492 out.endTag(null, TAG_MIN_PASSWORD_NUMERIC);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700493 }
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700494 if (minimumPasswordSymbols != DEF_MINIMUM_PASSWORD_SYMBOLS) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800495 out.startTag(null, TAG_MIN_PASSWORD_SYMBOLS);
496 out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordSymbols));
497 out.endTag(null, TAG_MIN_PASSWORD_SYMBOLS);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700498 }
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700499 if (minimumPasswordNonLetter > DEF_MINIMUM_PASSWORD_NON_LETTER) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800500 out.startTag(null, TAG_MIN_PASSWORD_NONLETTER);
501 out.attribute(null, ATTR_VALUE, Integer.toString(minimumPasswordNonLetter));
502 out.endTag(null, TAG_MIN_PASSWORD_NONLETTER);
Konstantin Lopyrevc8577402010-06-04 17:15:02 -0700503 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800504 }
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700505 if (maximumTimeToUnlock != DEF_MAXIMUM_TIME_TO_UNLOCK) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800506 out.startTag(null, TAG_MAX_TIME_TO_UNLOCK);
507 out.attribute(null, ATTR_VALUE, Long.toString(maximumTimeToUnlock));
508 out.endTag(null, TAG_MAX_TIME_TO_UNLOCK);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800509 }
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700510 if (maximumFailedPasswordsForWipe != DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800511 out.startTag(null, TAG_MAX_FAILED_PASSWORD_WIPE);
512 out.attribute(null, ATTR_VALUE, Integer.toString(maximumFailedPasswordsForWipe));
513 out.endTag(null, TAG_MAX_FAILED_PASSWORD_WIPE);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800514 }
Oscar Montemayor69238c62010-08-03 10:51:06 -0700515 if (specifiesGlobalProxy) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800516 out.startTag(null, TAG_SPECIFIES_GLOBAL_PROXY);
517 out.attribute(null, ATTR_VALUE, Boolean.toString(specifiesGlobalProxy));
518 out.endTag(null, TAG_SPECIFIES_GLOBAL_PROXY);
Oscar Montemayor69238c62010-08-03 10:51:06 -0700519 if (globalProxySpec != null) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800520 out.startTag(null, TAG_GLOBAL_PROXY_SPEC);
521 out.attribute(null, ATTR_VALUE, globalProxySpec);
522 out.endTag(null, TAG_GLOBAL_PROXY_SPEC);
Oscar Montemayor69238c62010-08-03 10:51:06 -0700523 }
524 if (globalProxyExclusionList != null) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800525 out.startTag(null, TAG_GLOBAL_PROXY_EXCLUSION_LIST);
526 out.attribute(null, ATTR_VALUE, globalProxyExclusionList);
527 out.endTag(null, TAG_GLOBAL_PROXY_EXCLUSION_LIST);
Oscar Montemayor69238c62010-08-03 10:51:06 -0700528 }
529 }
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700530 if (passwordExpirationTimeout != DEF_PASSWORD_EXPIRATION_TIMEOUT) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800531 out.startTag(null, TAG_PASSWORD_EXPIRATION_TIMEOUT);
532 out.attribute(null, ATTR_VALUE, Long.toString(passwordExpirationTimeout));
533 out.endTag(null, TAG_PASSWORD_EXPIRATION_TIMEOUT);
Jim Millera4e28d12010-11-08 16:15:47 -0800534 }
Dianne Hackbornd998acb2011-05-25 10:48:28 -0700535 if (passwordExpirationDate != DEF_PASSWORD_EXPIRATION_DATE) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800536 out.startTag(null, TAG_PASSWORD_EXPIRATION_DATE);
537 out.attribute(null, ATTR_VALUE, Long.toString(passwordExpirationDate));
538 out.endTag(null, TAG_PASSWORD_EXPIRATION_DATE);
Jim Millera4e28d12010-11-08 16:15:47 -0800539 }
Andy Stadler22dbfda2011-01-17 12:47:31 -0800540 if (encryptionRequested) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800541 out.startTag(null, TAG_ENCRYPTION_REQUESTED);
542 out.attribute(null, ATTR_VALUE, Boolean.toString(encryptionRequested));
543 out.endTag(null, TAG_ENCRYPTION_REQUESTED);
Andy Stadler22dbfda2011-01-17 12:47:31 -0800544 }
Ben Komalo2447edd2011-05-09 16:05:33 -0700545 if (disableCamera) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800546 out.startTag(null, TAG_DISABLE_CAMERA);
547 out.attribute(null, ATTR_VALUE, Boolean.toString(disableCamera));
548 out.endTag(null, TAG_DISABLE_CAMERA);
Ben Komalo2447edd2011-05-09 16:05:33 -0700549 }
Adam Connors210fe212014-07-17 15:41:43 +0100550 if (disableCallerId) {
551 out.startTag(null, TAG_DISABLE_CALLER_ID);
552 out.attribute(null, ATTR_VALUE, Boolean.toString(disableCallerId));
553 out.endTag(null, TAG_DISABLE_CALLER_ID);
554 }
Sander Alewijnsed2a1eec2014-07-09 12:57:05 +0100555 if (disableScreenCapture) {
556 out.startTag(null, TAG_DISABLE_SCREEN_CAPTURE);
557 out.attribute(null, ATTR_VALUE, Boolean.toString(disableScreenCapture));
558 out.endTag(null, TAG_DISABLE_SCREEN_CAPTURE);
559 }
Sander Alewijnse0ced6272014-08-26 11:18:26 +0100560 if (requireAutoTime) {
561 out.startTag(null, TAG_REQUIRE_AUTO_TIME);
562 out.attribute(null, ATTR_VALUE, Boolean.toString(requireAutoTime));
563 out.endTag(null, TAG_REQUIRE_AUTO_TIME);
564 }
Jim Miller48b9b0d2012-09-19 23:16:50 -0700565 if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
Amith Yamasanief38a102013-12-13 09:05:26 -0800566 out.startTag(null, TAG_DISABLE_KEYGUARD_FEATURES);
567 out.attribute(null, ATTR_VALUE, Integer.toString(disabledKeyguardFeatures));
568 out.endTag(null, TAG_DISABLE_KEYGUARD_FEATURES);
Jim Millerb8ec4702012-08-31 17:19:10 -0700569 }
Sander Alewijnse5c02db62014-05-07 10:46:57 +0100570 if (!accountTypesWithManagementDisabled.isEmpty()) {
571 out.startTag(null, TAG_DISABLE_ACCOUNT_MANAGEMENT);
572 for (String ac : accountTypesWithManagementDisabled) {
573 out.startTag(null, TAG_ACCOUNT_TYPE);
574 out.attribute(null, ATTR_VALUE, ac);
575 out.endTag(null, TAG_ACCOUNT_TYPE);
576 }
577 out.endTag(null, TAG_DISABLE_ACCOUNT_MANAGEMENT);
578 }
Jim Millere303bf42014-08-26 17:12:29 -0700579 if (!trustAgentInfos.isEmpty()) {
580 Set<Entry<String, TrustAgentInfo>> set = trustAgentInfos.entrySet();
Jim Miller604e7552014-07-18 19:00:02 -0700581 out.startTag(null, TAG_MANAGE_TRUST_AGENT_FEATURES);
Jim Millere303bf42014-08-26 17:12:29 -0700582 for (Entry<String, TrustAgentInfo> entry : set) {
583 TrustAgentInfo trustAgentInfo = entry.getValue();
Jim Miller604e7552014-07-18 19:00:02 -0700584 out.startTag(null, TAG_TRUST_AGENT_COMPONENT);
Jim Millere303bf42014-08-26 17:12:29 -0700585 out.attribute(null, ATTR_VALUE, entry.getKey());
586 if (trustAgentInfo.options != null) {
587 out.startTag(null, TAG_TRUST_AGENT_COMPONENT_OPTIONS);
588 try {
589 trustAgentInfo.options.saveToXml(out);
590 } catch (XmlPullParserException e) {
591 Log.e(LOG_TAG, "Failed to save TrustAgent options", e);
592 }
593 out.endTag(null, TAG_TRUST_AGENT_COMPONENT_OPTIONS);
Jim Miller604e7552014-07-18 19:00:02 -0700594 }
595 out.endTag(null, TAG_TRUST_AGENT_COMPONENT);
596 }
597 out.endTag(null, TAG_MANAGE_TRUST_AGENT_FEATURES);
598 }
Svetoslav976e8bd2014-07-16 15:12:03 -0700599 if (crossProfileWidgetProviders != null && !crossProfileWidgetProviders.isEmpty()) {
600 out.startTag(null, TAG_CROSS_PROFILE_WIDGET_PROVIDERS);
601 final int providerCount = crossProfileWidgetProviders.size();
602 for (int i = 0; i < providerCount; i++) {
603 String provider = crossProfileWidgetProviders.get(i);
604 out.startTag(null, TAG_PROVIDER);
605 out.attribute(null, ATTR_VALUE, provider);
606 out.endTag(null, TAG_PROVIDER);
607 }
608 out.endTag(null, TAG_CROSS_PROFILE_WIDGET_PROVIDERS);
609 }
Kenny Guyfa80a4f2014-08-20 19:40:59 +0100610 writePackageListToXml(out, TAG_PERMITTED_ACCESSIBILITY_SERVICES,
611 permittedAccessiblityServices);
612 writePackageListToXml(out, TAG_PERMITTED_IMES, permittedInputMethods);
613 }
614
615 void writePackageListToXml(XmlSerializer out, String outerTag,
616 List<String> packageList)
617 throws IllegalArgumentException, IllegalStateException, IOException {
618 if (packageList == null) {
619 return;
620 }
621
622 out.startTag(null, outerTag);
623 for (String packageName : packageList) {
624 out.startTag(null, TAG_PACKAGE_LIST_ITEM);
625 out.attribute(null, ATTR_VALUE, packageName);
626 out.endTag(null, TAG_PACKAGE_LIST_ITEM);
627 }
628 out.endTag(null, outerTag);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800629 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700630
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800631 void readFromXml(XmlPullParser parser)
632 throws XmlPullParserException, IOException {
633 int outerDepth = parser.getDepth();
634 int type;
Jim Miller604e7552014-07-18 19:00:02 -0700635 while ((type=parser.next()) != END_DOCUMENT
636 && (type != END_TAG || parser.getDepth() > outerDepth)) {
637 if (type == END_TAG || type == TEXT) {
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800638 continue;
639 }
640 String tag = parser.getName();
Amith Yamasanief38a102013-12-13 09:05:26 -0800641 if (TAG_POLICIES.equals(tag)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800642 info.readPoliciesFromXml(parser);
Amith Yamasanief38a102013-12-13 09:05:26 -0800643 } else if (TAG_PASSWORD_QUALITY.equals(tag)) {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -0800644 passwordQuality = Integer.parseInt(
Amith Yamasanief38a102013-12-13 09:05:26 -0800645 parser.getAttributeValue(null, ATTR_VALUE));
646 } else if (TAG_MIN_PASSWORD_LENGTH.equals(tag)) {
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800647 minimumPasswordLength = Integer.parseInt(
Amith Yamasanief38a102013-12-13 09:05:26 -0800648 parser.getAttributeValue(null, ATTR_VALUE));
649 } else if (TAG_PASSWORD_HISTORY_LENGTH.equals(tag)) {
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700650 passwordHistoryLength = Integer.parseInt(
Amith Yamasanief38a102013-12-13 09:05:26 -0800651 parser.getAttributeValue(null, ATTR_VALUE));
652 } else if (TAG_MIN_PASSWORD_UPPERCASE.equals(tag)) {
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700653 minimumPasswordUpperCase = Integer.parseInt(
Amith Yamasanief38a102013-12-13 09:05:26 -0800654 parser.getAttributeValue(null, ATTR_VALUE));
655 } else if (TAG_MIN_PASSWORD_LOWERCASE.equals(tag)) {
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700656 minimumPasswordLowerCase = Integer.parseInt(
Amith Yamasanief38a102013-12-13 09:05:26 -0800657 parser.getAttributeValue(null, ATTR_VALUE));
658 } else if (TAG_MIN_PASSWORD_LETTERS.equals(tag)) {
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700659 minimumPasswordLetters = Integer.parseInt(
Amith Yamasanief38a102013-12-13 09:05:26 -0800660 parser.getAttributeValue(null, ATTR_VALUE));
661 } else if (TAG_MIN_PASSWORD_NUMERIC.equals(tag)) {
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700662 minimumPasswordNumeric = Integer.parseInt(
Amith Yamasanief38a102013-12-13 09:05:26 -0800663 parser.getAttributeValue(null, ATTR_VALUE));
664 } else if (TAG_MIN_PASSWORD_SYMBOLS.equals(tag)) {
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700665 minimumPasswordSymbols = Integer.parseInt(
Amith Yamasanief38a102013-12-13 09:05:26 -0800666 parser.getAttributeValue(null, ATTR_VALUE));
667 } else if (TAG_MIN_PASSWORD_NONLETTER.equals(tag)) {
Konstantin Lopyrevc8577402010-06-04 17:15:02 -0700668 minimumPasswordNonLetter = Integer.parseInt(
Amith Yamasanief38a102013-12-13 09:05:26 -0800669 parser.getAttributeValue(null, ATTR_VALUE));
670 } else if (TAG_MAX_TIME_TO_UNLOCK.equals(tag)) {
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800671 maximumTimeToUnlock = Long.parseLong(
Amith Yamasanief38a102013-12-13 09:05:26 -0800672 parser.getAttributeValue(null, ATTR_VALUE));
673 } else if (TAG_MAX_FAILED_PASSWORD_WIPE.equals(tag)) {
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800674 maximumFailedPasswordsForWipe = Integer.parseInt(
Amith Yamasanief38a102013-12-13 09:05:26 -0800675 parser.getAttributeValue(null, ATTR_VALUE));
676 } else if (TAG_SPECIFIES_GLOBAL_PROXY.equals(tag)) {
Andy Stadler22dbfda2011-01-17 12:47:31 -0800677 specifiesGlobalProxy = Boolean.parseBoolean(
Amith Yamasanief38a102013-12-13 09:05:26 -0800678 parser.getAttributeValue(null, ATTR_VALUE));
679 } else if (TAG_GLOBAL_PROXY_SPEC.equals(tag)) {
Oscar Montemayor69238c62010-08-03 10:51:06 -0700680 globalProxySpec =
Amith Yamasanief38a102013-12-13 09:05:26 -0800681 parser.getAttributeValue(null, ATTR_VALUE);
682 } else if (TAG_GLOBAL_PROXY_EXCLUSION_LIST.equals(tag)) {
Oscar Montemayor69238c62010-08-03 10:51:06 -0700683 globalProxyExclusionList =
Amith Yamasanief38a102013-12-13 09:05:26 -0800684 parser.getAttributeValue(null, ATTR_VALUE);
685 } else if (TAG_PASSWORD_EXPIRATION_TIMEOUT.equals(tag)) {
Jim Millera4e28d12010-11-08 16:15:47 -0800686 passwordExpirationTimeout = Long.parseLong(
Amith Yamasanief38a102013-12-13 09:05:26 -0800687 parser.getAttributeValue(null, ATTR_VALUE));
688 } else if (TAG_PASSWORD_EXPIRATION_DATE.equals(tag)) {
Jim Millera4e28d12010-11-08 16:15:47 -0800689 passwordExpirationDate = Long.parseLong(
Amith Yamasanief38a102013-12-13 09:05:26 -0800690 parser.getAttributeValue(null, ATTR_VALUE));
691 } else if (TAG_ENCRYPTION_REQUESTED.equals(tag)) {
Andy Stadler22dbfda2011-01-17 12:47:31 -0800692 encryptionRequested = Boolean.parseBoolean(
Amith Yamasanief38a102013-12-13 09:05:26 -0800693 parser.getAttributeValue(null, ATTR_VALUE));
694 } else if (TAG_DISABLE_CAMERA.equals(tag)) {
Ben Komalo2447edd2011-05-09 16:05:33 -0700695 disableCamera = Boolean.parseBoolean(
Amith Yamasanief38a102013-12-13 09:05:26 -0800696 parser.getAttributeValue(null, ATTR_VALUE));
Adam Connors210fe212014-07-17 15:41:43 +0100697 } else if (TAG_DISABLE_CALLER_ID.equals(tag)) {
698 disableCallerId = Boolean.parseBoolean(
699 parser.getAttributeValue(null, ATTR_VALUE));
Sander Alewijnsed2a1eec2014-07-09 12:57:05 +0100700 } else if (TAG_DISABLE_SCREEN_CAPTURE.equals(tag)) {
701 disableScreenCapture = Boolean.parseBoolean(
702 parser.getAttributeValue(null, ATTR_VALUE));
Sander Alewijnse0ced6272014-08-26 11:18:26 +0100703 } else if (TAG_REQUIRE_AUTO_TIME.equals(tag)) {
704 requireAutoTime= Boolean.parseBoolean(
705 parser.getAttributeValue(null, ATTR_VALUE));
Amith Yamasanief38a102013-12-13 09:05:26 -0800706 } else if (TAG_DISABLE_KEYGUARD_FEATURES.equals(tag)) {
Amith Yamasani7077b3c2012-10-04 10:28:50 -0700707 disabledKeyguardFeatures = Integer.parseInt(
Amith Yamasanief38a102013-12-13 09:05:26 -0800708 parser.getAttributeValue(null, ATTR_VALUE));
Sander Alewijnse5c02db62014-05-07 10:46:57 +0100709 } else if (TAG_DISABLE_ACCOUNT_MANAGEMENT.equals(tag)) {
Jim Miller604e7552014-07-18 19:00:02 -0700710 accountTypesWithManagementDisabled = readDisableAccountInfo(parser, tag);
711 } else if (TAG_MANAGE_TRUST_AGENT_FEATURES.equals(tag)) {
Jim Millere303bf42014-08-26 17:12:29 -0700712 trustAgentInfos = getAllTrustAgentInfos(parser, tag);
Svetoslav976e8bd2014-07-16 15:12:03 -0700713 } else if (TAG_CROSS_PROFILE_WIDGET_PROVIDERS.equals(tag)) {
714 crossProfileWidgetProviders = getCrossProfileWidgetProviders(parser, tag);
Kenny Guyfa80a4f2014-08-20 19:40:59 +0100715 } else if (TAG_PERMITTED_ACCESSIBILITY_SERVICES.equals(tag)) {
716 permittedAccessiblityServices = readPackageList(parser, tag);
717 } else if (TAG_PERMITTED_IMES.equals(tag)) {
718 permittedInputMethods = readPackageList(parser, tag);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800719 } else {
Amith Yamasanief38a102013-12-13 09:05:26 -0800720 Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800721 }
722 XmlUtils.skipCurrentTag(parser);
723 }
724 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700725
Kenny Guyfa80a4f2014-08-20 19:40:59 +0100726 private List<String> readPackageList(XmlPullParser parser,
727 String tag) throws XmlPullParserException, IOException {
728 List<String> result = new ArrayList<String>();
729 int outerDepth = parser.getDepth();
730 int outerType;
731 while ((outerType=parser.next()) != XmlPullParser.END_DOCUMENT
732 && (outerType != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
733 if (outerType == XmlPullParser.END_TAG || outerType == XmlPullParser.TEXT) {
734 continue;
735 }
736 String outerTag = parser.getName();
737 if (TAG_PACKAGE_LIST_ITEM.equals(outerTag)) {
738 String packageName = parser.getAttributeValue(null, ATTR_VALUE);
739 if (packageName != null) {
740 result.add(packageName);
741 } else {
742 Slog.w(LOG_TAG, "Package name missing under " + outerTag);
743 }
744 } else {
745 Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + outerTag);
746 }
747 }
748 return result;
749 }
750
Jim Miller604e7552014-07-18 19:00:02 -0700751 private Set<String> readDisableAccountInfo(XmlPullParser parser, String tag)
752 throws XmlPullParserException, IOException {
753 int outerDepthDAM = parser.getDepth();
754 int typeDAM;
755 Set<String> result = new HashSet<String>();
756 while ((typeDAM=parser.next()) != END_DOCUMENT
757 && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
758 if (typeDAM == END_TAG || typeDAM == TEXT) {
759 continue;
760 }
761 String tagDAM = parser.getName();
762 if (TAG_ACCOUNT_TYPE.equals(tagDAM)) {
763 result.add(parser.getAttributeValue(null, ATTR_VALUE));
764 } else {
765 Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
766 }
767 }
768 return result;
769 }
770
Jim Millere303bf42014-08-26 17:12:29 -0700771 private HashMap<String, TrustAgentInfo> getAllTrustAgentInfos(
772 XmlPullParser parser, String tag) throws XmlPullParserException, IOException {
Jim Miller604e7552014-07-18 19:00:02 -0700773 int outerDepthDAM = parser.getDepth();
774 int typeDAM;
Jim Millere303bf42014-08-26 17:12:29 -0700775 HashMap<String, TrustAgentInfo> result = new HashMap<String, TrustAgentInfo>();
Jim Miller604e7552014-07-18 19:00:02 -0700776 while ((typeDAM=parser.next()) != END_DOCUMENT
777 && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
778 if (typeDAM == END_TAG || typeDAM == TEXT) {
779 continue;
780 }
781 String tagDAM = parser.getName();
782 if (TAG_TRUST_AGENT_COMPONENT.equals(tagDAM)) {
783 final String component = parser.getAttributeValue(null, ATTR_VALUE);
Jim Millere303bf42014-08-26 17:12:29 -0700784 final TrustAgentInfo trustAgentInfo = getTrustAgentInfo(parser, tag);
785 result.put(component, trustAgentInfo);
Jim Miller604e7552014-07-18 19:00:02 -0700786 } else {
787 Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
788 }
789 }
790 return result;
791 }
792
Jim Millere303bf42014-08-26 17:12:29 -0700793 private TrustAgentInfo getTrustAgentInfo(XmlPullParser parser, String tag)
Jim Miller604e7552014-07-18 19:00:02 -0700794 throws XmlPullParserException, IOException {
795 int outerDepthDAM = parser.getDepth();
796 int typeDAM;
Jim Millere303bf42014-08-26 17:12:29 -0700797 TrustAgentInfo result = new TrustAgentInfo(null);
Jim Miller604e7552014-07-18 19:00:02 -0700798 while ((typeDAM=parser.next()) != END_DOCUMENT
799 && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
800 if (typeDAM == END_TAG || typeDAM == TEXT) {
801 continue;
802 }
803 String tagDAM = parser.getName();
Jim Millere303bf42014-08-26 17:12:29 -0700804 if (TAG_TRUST_AGENT_COMPONENT_OPTIONS.equals(tagDAM)) {
805 PersistableBundle bundle = new PersistableBundle();
806 bundle.restoreFromXml(parser);
807 result.options = bundle;
Jim Miller604e7552014-07-18 19:00:02 -0700808 } else {
809 Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
810 }
811 }
812 return result;
813 }
814
Svetoslav976e8bd2014-07-16 15:12:03 -0700815 private List<String> getCrossProfileWidgetProviders(XmlPullParser parser, String tag)
816 throws XmlPullParserException, IOException {
817 int outerDepthDAM = parser.getDepth();
818 int typeDAM;
819 ArrayList<String> result = null;
820 while ((typeDAM=parser.next()) != END_DOCUMENT
821 && (typeDAM != END_TAG || parser.getDepth() > outerDepthDAM)) {
822 if (typeDAM == END_TAG || typeDAM == TEXT) {
823 continue;
824 }
825 String tagDAM = parser.getName();
826 if (TAG_PROVIDER.equals(tagDAM)) {
827 final String provider = parser.getAttributeValue(null, ATTR_VALUE);
828 if (result == null) {
829 result = new ArrayList<>();
830 }
831 result.add(provider);
832 } else {
833 Slog.w(LOG_TAG, "Unknown tag under " + tag + ": " + tagDAM);
834 }
835 }
836 return result;
837 }
838
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800839 void dump(String prefix, PrintWriter pw) {
840 pw.print(prefix); pw.print("uid="); pw.println(getUid());
841 pw.print(prefix); pw.println("policies:");
842 ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies();
843 if (pols != null) {
844 for (int i=0; i<pols.size(); i++) {
845 pw.print(prefix); pw.print(" "); pw.println(pols.get(i).tag);
846 }
847 }
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -0700848 pw.print(prefix); pw.print("passwordQuality=0x");
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700849 pw.println(Integer.toHexString(passwordQuality));
850 pw.print(prefix); pw.print("minimumPasswordLength=");
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800851 pw.println(minimumPasswordLength);
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700852 pw.print(prefix); pw.print("passwordHistoryLength=");
853 pw.println(passwordHistoryLength);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -0700854 pw.print(prefix); pw.print("minimumPasswordUpperCase=");
855 pw.println(minimumPasswordUpperCase);
856 pw.print(prefix); pw.print("minimumPasswordLowerCase=");
857 pw.println(minimumPasswordLowerCase);
858 pw.print(prefix); pw.print("minimumPasswordLetters=");
859 pw.println(minimumPasswordLetters);
860 pw.print(prefix); pw.print("minimumPasswordNumeric=");
861 pw.println(minimumPasswordNumeric);
862 pw.print(prefix); pw.print("minimumPasswordSymbols=");
863 pw.println(minimumPasswordSymbols);
Konstantin Lopyrevc8577402010-06-04 17:15:02 -0700864 pw.print(prefix); pw.print("minimumPasswordNonLetter=");
865 pw.println(minimumPasswordNonLetter);
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800866 pw.print(prefix); pw.print("maximumTimeToUnlock=");
867 pw.println(maximumTimeToUnlock);
868 pw.print(prefix); pw.print("maximumFailedPasswordsForWipe=");
869 pw.println(maximumFailedPasswordsForWipe);
Oscar Montemayor69238c62010-08-03 10:51:06 -0700870 pw.print(prefix); pw.print("specifiesGlobalProxy=");
871 pw.println(specifiesGlobalProxy);
Jim Millera4e28d12010-11-08 16:15:47 -0800872 pw.print(prefix); pw.print("passwordExpirationTimeout=");
873 pw.println(passwordExpirationTimeout);
874 pw.print(prefix); pw.print("passwordExpirationDate=");
875 pw.println(passwordExpirationDate);
Oscar Montemayor69238c62010-08-03 10:51:06 -0700876 if (globalProxySpec != null) {
877 pw.print(prefix); pw.print("globalProxySpec=");
878 pw.println(globalProxySpec);
879 }
880 if (globalProxyExclusionList != null) {
881 pw.print(prefix); pw.print("globalProxyEclusionList=");
882 pw.println(globalProxyExclusionList);
883 }
Andy Stadler22dbfda2011-01-17 12:47:31 -0800884 pw.print(prefix); pw.print("encryptionRequested=");
885 pw.println(encryptionRequested);
Ben Komalo2447edd2011-05-09 16:05:33 -0700886 pw.print(prefix); pw.print("disableCamera=");
887 pw.println(disableCamera);
Adam Connors210fe212014-07-17 15:41:43 +0100888 pw.print(prefix); pw.print("disableCallerId=");
889 pw.println(disableCallerId);
Sander Alewijnsed2a1eec2014-07-09 12:57:05 +0100890 pw.print(prefix); pw.print("disableScreenCapture=");
891 pw.println(disableScreenCapture);
Sander Alewijnse0ced6272014-08-26 11:18:26 +0100892 pw.print(prefix); pw.print("requireAutoTime=");
893 pw.println(requireAutoTime);
Amith Yamasani7077b3c2012-10-04 10:28:50 -0700894 pw.print(prefix); pw.print("disabledKeyguardFeatures=");
895 pw.println(disabledKeyguardFeatures);
Svetoslav976e8bd2014-07-16 15:12:03 -0700896 pw.print(prefix); pw.print("crossProfileWidgetProviders=");
897 pw.println(crossProfileWidgetProviders);
Kenny Guyfa80a4f2014-08-20 19:40:59 +0100898 if (!(permittedAccessiblityServices == null)) {
899 pw.print(prefix); pw.print("permittedAccessibilityServices=");
900 pw.println(permittedAccessiblityServices.toString());
901 }
902 if (!(permittedInputMethods == null)) {
903 pw.print(prefix); pw.print("permittedInputMethods=");
904 pw.println(permittedInputMethods.toString());
905 }
Dianne Hackborn87bba1e2010-02-26 17:25:54 -0800906 }
Dianne Hackborn21f1bd12010-02-19 17:02:21 -0800907 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700908
Amith Yamasania0116af2014-12-04 14:49:24 -0800909 private void handlePackagesChanged(String packageName, int userHandle) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700910 boolean removed = false;
Amith Yamasanief38a102013-12-13 09:05:26 -0800911 if (DBG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700912 DevicePolicyData policy = getUserData(userHandle);
913 IPackageManager pm = AppGlobals.getPackageManager();
Fyodor Kupolovd01ff6d2014-11-12 10:46:50 -0800914 synchronized (this) {
915 for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
916 ActiveAdmin aa = policy.mAdminList.get(i);
917 try {
Amith Yamasania0116af2014-12-04 14:49:24 -0800918 // If we're checking all packages or if the specific one we're checking matches,
919 // then check if the package and receiver still exist.
920 final String adminPackage = aa.info.getPackageName();
921 if (packageName == null || packageName.equals(adminPackage)) {
922 if (pm.getPackageInfo(adminPackage, 0, userHandle) == null
923 || pm.getReceiverInfo(aa.info.getComponent(), 0, userHandle)
924 == null) {
925 removed = true;
926 policy.mAdminList.remove(i);
927 policy.mAdminMap.remove(aa.info.getComponent());
928 }
Fyodor Kupolovd01ff6d2014-11-12 10:46:50 -0800929 }
930 } catch (RemoteException re) {
931 // Shouldn't happen
Dianne Hackborn8ea138c2010-01-26 18:01:04 -0800932 }
933 }
Fyodor Kupolovd01ff6d2014-11-12 10:46:50 -0800934 if (removed) {
935 validatePasswordOwnerLocked(policy);
936 syncDeviceCapabilitiesLocked(policy);
937 saveSettingsLocked(policy.mUserHandle);
938 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700939 }
Dianne Hackbornd6847842010-01-12 18:14:19 -0800940 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -0700941
Dianne Hackbornd6847842010-01-12 18:14:19 -0800942 /**
943 * Instantiates the service.
944 */
945 public DevicePolicyManagerService(Context context) {
946 mContext = context;
Jessica Hummel91da58d2014-04-10 17:39:43 +0100947 mUserManager = UserManager.get(mContext);
Amith Yamasani44a01b72013-09-16 10:44:57 -0700948 mHasFeature = context.getPackageManager().hasSystemFeature(
949 PackageManager.FEATURE_DEVICE_ADMIN);
Jeff Brown5ce1cb22014-11-06 19:05:33 -0800950 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
951 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
952 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM");
Svet Ganov6bd70252014-08-20 09:47:47 -0700953 mLocalService = new LocalService();
Amith Yamasani44a01b72013-09-16 10:44:57 -0700954 if (!mHasFeature) {
955 // Skip the rest of the initialization
956 return;
957 }
Jim Millera4e28d12010-11-08 16:15:47 -0800958 IntentFilter filter = new IntentFilter();
959 filter.addAction(Intent.ACTION_BOOT_COMPLETED);
960 filter.addAction(ACTION_EXPIRED_PASSWORD_NOTIFICATION);
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700961 filter.addAction(Intent.ACTION_USER_REMOVED);
962 filter.addAction(Intent.ACTION_USER_STARTED);
Maggie Benthall0469f412013-09-05 15:30:26 -0400963 filter.addAction(KeyChain.ACTION_STORAGE_CHANGED);
Dianne Hackbornd83a0962014-05-02 16:28:33 -0700964 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700965 context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
966 filter = new IntentFilter();
967 filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
968 filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
969 filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
Amith Yamasani71e6c692013-03-24 17:39:28 -0700970 filter.addAction(Intent.ACTION_PACKAGE_ADDED);
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700971 filter.addDataScheme("package");
972 context.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler);
Svetoslav976e8bd2014-07-16 15:12:03 -0700973
Svet Ganov6bd70252014-08-20 09:47:47 -0700974 LocalServices.addService(DevicePolicyManagerInternal.class, mLocalService);
Amith Yamasani599dd7c2012-09-14 23:20:08 -0700975 }
976
977 /**
978 * Creates and loads the policy data from xml.
979 * @param userHandle the user for whom to load the policy data
980 * @return
981 */
982 DevicePolicyData getUserData(int userHandle) {
983 synchronized (this) {
984 DevicePolicyData policy = mUserData.get(userHandle);
985 if (policy == null) {
986 policy = new DevicePolicyData(userHandle);
987 mUserData.append(userHandle, policy);
988 loadSettingsLocked(policy, userHandle);
989 }
990 return policy;
991 }
992 }
993
Benjamin Franzfadb2b32015-01-14 18:22:42 +0000994 /**
995 * Creates and loads the policy data from xml for data that is shared between
996 * various profiles of a user. In contrast to {@link #getUserData(int)}
997 * it allows access to data of users other than the calling user.
998 *
999 * This function should only be used for shared data, e.g. everything regarding
1000 * passwords and should be removed once multiple screen locks are present.
1001 * @param userHandle the user for whom to load the policy data
1002 * @return
1003 */
1004 DevicePolicyData getUserDataUnchecked(int userHandle) {
1005 long ident = Binder.clearCallingIdentity();
1006 try {
1007 return getUserData(userHandle);
1008 } finally {
1009 Binder.restoreCallingIdentity(ident);
1010 }
1011 }
1012
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001013 void removeUserData(int userHandle) {
1014 synchronized (this) {
1015 if (userHandle == UserHandle.USER_OWNER) {
Amith Yamasanief38a102013-12-13 09:05:26 -08001016 Slog.w(LOG_TAG, "Tried to remove device policy file for user 0! Ignoring.");
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001017 return;
1018 }
Amith Yamasani9348ac82014-02-10 13:43:18 -08001019 if (mDeviceOwner != null) {
1020 mDeviceOwner.removeProfileOwner(userHandle);
1021 mDeviceOwner.writeOwnerFile();
1022 }
Adam Connors776c5552014-01-09 10:42:56 +00001023
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001024 DevicePolicyData policy = mUserData.get(userHandle);
1025 if (policy != null) {
1026 mUserData.remove(userHandle);
1027 }
1028 File policyFile = new File(Environment.getUserSystemDirectory(userHandle),
1029 DEVICE_POLICIES_XML);
1030 policyFile.delete();
Amith Yamasanief38a102013-12-13 09:05:26 -08001031 Slog.i(LOG_TAG, "Removed device policy file " + policyFile.getAbsolutePath());
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001032 }
Sander Alewijnsea87863a2014-07-29 12:01:38 +01001033 updateScreenCaptureDisabledInWindowManager(userHandle, false /* default value */);
Jim Millera4e28d12010-11-08 16:15:47 -08001034 }
1035
Amith Yamasani71e6c692013-03-24 17:39:28 -07001036 void loadDeviceOwner() {
1037 synchronized (this) {
Adam Connors776c5552014-01-09 10:42:56 +00001038 mDeviceOwner = DeviceOwner.load();
Amith Yamasani71e6c692013-03-24 17:39:28 -07001039 }
1040 }
1041
Andy Stadler043116a2010-11-29 17:43:32 -08001042 /**
1043 * Set an alarm for an upcoming event - expiration warning, expiration, or post-expiration
1044 * reminders. Clears alarm if no expirations are configured.
1045 */
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001046 protected void setExpirationAlarmCheckLocked(Context context, DevicePolicyData policy) {
1047 final long expiration = getPasswordExpirationLocked(null, policy.mUserHandle);
Jim Millera4e28d12010-11-08 16:15:47 -08001048 final long now = System.currentTimeMillis();
1049 final long timeToExpire = expiration - now;
1050 final long alarmTime;
Andy Stadler043116a2010-11-29 17:43:32 -08001051 if (expiration == 0) {
1052 // No expirations are currently configured: Cancel alarm.
1053 alarmTime = 0;
1054 } else if (timeToExpire <= 0) {
1055 // The password has already expired: Repeat every 24 hours.
Jim Millera4e28d12010-11-08 16:15:47 -08001056 alarmTime = now + MS_PER_DAY;
Andy Stadler043116a2010-11-29 17:43:32 -08001057 } else {
1058 // Selecting the next alarm time: Roll forward to the next 24 hour multiple before
1059 // the expiration time.
1060 long alarmInterval = timeToExpire % MS_PER_DAY;
1061 if (alarmInterval == 0) {
1062 alarmInterval = MS_PER_DAY;
1063 }
1064 alarmTime = now + alarmInterval;
Jim Millera4e28d12010-11-08 16:15:47 -08001065 }
1066
Andy Stadler1f35d482010-11-19 15:39:41 -08001067 long token = Binder.clearCallingIdentity();
1068 try {
1069 AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001070 PendingIntent pi = PendingIntent.getBroadcastAsUser(context, REQUEST_EXPIRE_PASSWORD,
Andy Stadler1f35d482010-11-19 15:39:41 -08001071 new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION),
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001072 PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT,
1073 new UserHandle(policy.mUserHandle));
Andy Stadler1f35d482010-11-19 15:39:41 -08001074 am.cancel(pi);
Andy Stadler043116a2010-11-29 17:43:32 -08001075 if (alarmTime != 0) {
1076 am.set(AlarmManager.RTC, alarmTime, pi);
1077 }
Andy Stadler1f35d482010-11-19 15:39:41 -08001078 } finally {
1079 Binder.restoreCallingIdentity(token);
1080 }
Dianne Hackbornd6847842010-01-12 18:14:19 -08001081 }
1082
Jim Miller93c518e2012-01-17 15:55:31 -08001083 private IWindowManager getWindowManager() {
1084 if (mIWindowManager == null) {
1085 IBinder b = ServiceManager.getService(Context.WINDOW_SERVICE);
1086 mIWindowManager = IWindowManager.Stub.asInterface(b);
1087 }
1088 return mIWindowManager;
1089 }
1090
Maggie Benthall0469f412013-09-05 15:30:26 -04001091 private NotificationManager getNotificationManager() {
1092 if (mNotificationManager == null) {
1093 mNotificationManager =
1094 (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
1095 }
1096 return mNotificationManager;
1097 }
1098
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001099 ActiveAdmin getActiveAdminUncheckedLocked(ComponentName who, int userHandle) {
1100 ActiveAdmin admin = getUserData(userHandle).mAdminMap.get(who);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08001101 if (admin != null
1102 && who.getPackageName().equals(admin.info.getActivityInfo().packageName)
1103 && who.getClassName().equals(admin.info.getActivityInfo().name)) {
1104 return admin;
1105 }
1106 return null;
1107 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001108
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08001109 ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
1110 throws SecurityException {
Dianne Hackborn254cb442010-01-27 19:23:59 -08001111 final int callingUid = Binder.getCallingUid();
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001112 final int userHandle = UserHandle.getUserId(callingUid);
1113 final DevicePolicyData policy = getUserData(userHandle);
Robin Lee5c921da2014-03-24 15:11:35 +00001114
1115 List<ActiveAdmin> candidates = new ArrayList<ActiveAdmin>();
1116
1117 // Build a list of admins for this uid matching the given ComponentName
Dianne Hackborn254cb442010-01-27 19:23:59 -08001118 if (who != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001119 ActiveAdmin admin = policy.mAdminMap.get(who);
Dianne Hackborn254cb442010-01-27 19:23:59 -08001120 if (admin == null) {
1121 throw new SecurityException("No active admin " + who);
1122 }
1123 if (admin.getUid() != callingUid) {
1124 throw new SecurityException("Admin " + who + " is not owned by uid "
1125 + Binder.getCallingUid());
1126 }
Robin Lee5c921da2014-03-24 15:11:35 +00001127 candidates.add(admin);
Dianne Hackborn254cb442010-01-27 19:23:59 -08001128 } else {
Robin Lee5c921da2014-03-24 15:11:35 +00001129 for (ActiveAdmin admin : policy.mAdminList) {
1130 if (admin.getUid() == callingUid) {
1131 candidates.add(admin);
1132 }
1133 }
1134 }
1135
1136 // Try to find an admin which can use reqPolicy
1137 for (ActiveAdmin admin : candidates) {
1138 boolean ownsDevice = isDeviceOwner(admin.info.getPackageName());
1139 boolean ownsProfile = (getProfileOwner(userHandle) != null
Amith Yamasanibf3a9462014-07-28 14:26:42 -07001140 && getProfileOwner(userHandle).getPackageName()
1141 .equals(admin.info.getPackageName()));
Robin Lee5c921da2014-03-24 15:11:35 +00001142
1143 if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
1144 if (ownsDevice) {
1145 return admin;
1146 }
1147 } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
1148 if (ownsDevice || ownsProfile) {
1149 return admin;
1150 }
1151 } else {
1152 if (admin.info.usesPolicy(reqPolicy)) {
Dianne Hackborn254cb442010-01-27 19:23:59 -08001153 return admin;
1154 }
1155 }
Robin Lee5c921da2014-03-24 15:11:35 +00001156 }
1157
1158 if (who != null) {
Robin Lee122c5952014-06-11 17:39:45 +01001159 if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
1160 throw new SecurityException("Admin " + candidates.get(0).info.getComponent()
1161 + " does not own the device");
1162 }
1163 if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
1164 throw new SecurityException("Admin " + candidates.get(0).info.getComponent()
1165 + " does not own the profile");
1166 }
Robin Lee5c921da2014-03-24 15:11:35 +00001167 throw new SecurityException("Admin " + candidates.get(0).info.getComponent()
1168 + " did not specify uses-policy for: "
1169 + candidates.get(0).info.getTagForPolicy(reqPolicy));
1170 } else {
Dianne Hackborn254cb442010-01-27 19:23:59 -08001171 throw new SecurityException("No active admin owned by uid "
Robin Lee122c5952014-06-11 17:39:45 +01001172 + Binder.getCallingUid() + " for policy #" + reqPolicy);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08001173 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08001174 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001175
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08001176 void sendAdminCommandLocked(ActiveAdmin admin, String action) {
Dianne Hackbornd998acb2011-05-25 10:48:28 -07001177 sendAdminCommandLocked(admin, action, null);
1178 }
1179
Jason Monk03978a42014-06-10 15:05:30 -04001180 void sendAdminCommandLocked(ActiveAdmin admin, String action, BroadcastReceiver result) {
1181 sendAdminCommandLocked(admin, action, null, result);
1182 }
1183
Jessica Hummel91da58d2014-04-10 17:39:43 +01001184 /**
1185 * Send an update to one specific admin, get notified when that admin returns a result.
1186 */
Jason Monk03978a42014-06-10 15:05:30 -04001187 void sendAdminCommandLocked(ActiveAdmin admin, String action, Bundle adminExtras,
1188 BroadcastReceiver result) {
Dianne Hackbornd6847842010-01-12 18:14:19 -08001189 Intent intent = new Intent(action);
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08001190 intent.setComponent(admin.info.getComponent());
Jim Millera4e28d12010-11-08 16:15:47 -08001191 if (action.equals(DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING)) {
1192 intent.putExtra("expiration", admin.passwordExpirationDate);
1193 }
Jason Monk03978a42014-06-10 15:05:30 -04001194 if (adminExtras != null) {
1195 intent.putExtras(adminExtras);
1196 }
Dianne Hackbornd998acb2011-05-25 10:48:28 -07001197 if (result != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001198 mContext.sendOrderedBroadcastAsUser(intent, admin.getUserHandle(),
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001199 null, result, mHandler, Activity.RESULT_OK, null, null);
Dianne Hackbornd998acb2011-05-25 10:48:28 -07001200 } else {
Kenny Guy73a41d22014-06-05 16:51:24 +01001201 mContext.sendBroadcastAsUser(intent, admin.getUserHandle());
Dianne Hackbornd998acb2011-05-25 10:48:28 -07001202 }
Dianne Hackbornd6847842010-01-12 18:14:19 -08001203 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001204
Jessica Hummel91da58d2014-04-10 17:39:43 +01001205 /**
1206 * Send an update to all admins of a user that enforce a specified policy.
1207 */
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001208 void sendAdminCommandLocked(String action, int reqPolicy, int userHandle) {
1209 final DevicePolicyData policy = getUserData(userHandle);
1210 final int count = policy.mAdminList.size();
1211 if (count > 0) {
1212 for (int i = 0; i < count; i++) {
Jessica Hummel91da58d2014-04-10 17:39:43 +01001213 final ActiveAdmin admin = policy.mAdminList.get(i);
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08001214 if (admin.info.usesPolicy(reqPolicy)) {
1215 sendAdminCommandLocked(admin, action);
1216 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08001217 }
Dianne Hackborn4141d032010-01-21 16:29:00 -08001218 }
1219 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001220
Jessica Hummel91da58d2014-04-10 17:39:43 +01001221 /**
1222 * Send an update intent to all admins of a user and its profiles. Only send to admins that
1223 * enforce a specified policy.
1224 */
1225 private void sendAdminCommandToSelfAndProfilesLocked(String action, int reqPolicy,
1226 int userHandle) {
1227 List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
1228 for (UserInfo ui : profiles) {
Jim Millere303bf42014-08-26 17:12:29 -07001229 int id = ui.id;
Jessica Hummel91da58d2014-04-10 17:39:43 +01001230 sendAdminCommandLocked(action, reqPolicy, id);
1231 }
1232 }
1233
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001234 void removeActiveAdminLocked(final ComponentName adminReceiver, int userHandle) {
1235 final ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08001236 if (admin != null) {
Fyodor Kupolov96fb9322014-12-01 15:08:09 -08001237 synchronized (this) {
1238 getUserData(userHandle).mRemovingAdmins.add(adminReceiver);
1239 }
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08001240 sendAdminCommandLocked(admin,
Dianne Hackbornd998acb2011-05-25 10:48:28 -07001241 DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLED,
1242 new BroadcastReceiver() {
1243 @Override
1244 public void onReceive(Context context, Intent intent) {
Dianne Hackborn2fe8fb22012-06-15 17:05:25 -07001245 synchronized (DevicePolicyManagerService.this) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001246 int userHandle = admin.getUserHandle().getIdentifier();
1247 DevicePolicyData policy = getUserData(userHandle);
Dianne Hackbornd998acb2011-05-25 10:48:28 -07001248 boolean doProxyCleanup = admin.info.usesPolicy(
1249 DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001250 policy.mAdminList.remove(admin);
1251 policy.mAdminMap.remove(adminReceiver);
1252 validatePasswordOwnerLocked(policy);
1253 syncDeviceCapabilitiesLocked(policy);
Dianne Hackbornd998acb2011-05-25 10:48:28 -07001254 if (doProxyCleanup) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001255 resetGlobalProxyLocked(getUserData(userHandle));
Dianne Hackbornd998acb2011-05-25 10:48:28 -07001256 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001257 saveSettingsLocked(userHandle);
1258 updateMaximumTimeToLockLocked(policy);
Fyodor Kupolov96fb9322014-12-01 15:08:09 -08001259 policy.mRemovingAdmins.remove(adminReceiver);
Dianne Hackbornd998acb2011-05-25 10:48:28 -07001260 }
1261 }
Fyodor Kupolov96fb9322014-12-01 15:08:09 -08001262 });
Dianne Hackbornd6847842010-01-12 18:14:19 -08001263 }
1264 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001265
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001266 public DeviceAdminInfo findAdmin(ComponentName adminName, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07001267 if (!mHasFeature) {
1268 return null;
1269 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001270 enforceCrossUserPermission(userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001271 Intent resolveIntent = new Intent();
1272 resolveIntent.setComponent(adminName);
1273 List<ResolveInfo> infos = mContext.getPackageManager().queryBroadcastReceivers(
Amith Yamasani71e6c692013-03-24 17:39:28 -07001274 resolveIntent,
1275 PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
1276 userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001277 if (infos == null || infos.size() <= 0) {
1278 throw new IllegalArgumentException("Unknown admin: " + adminName);
1279 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001280
Dianne Hackbornd6847842010-01-12 18:14:19 -08001281 try {
1282 return new DeviceAdminInfo(mContext, infos.get(0));
1283 } catch (XmlPullParserException e) {
Amith Yamasanief38a102013-12-13 09:05:26 -08001284 Slog.w(LOG_TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName,
1285 e);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001286 return null;
1287 } catch (IOException e) {
Amith Yamasanief38a102013-12-13 09:05:26 -08001288 Slog.w(LOG_TAG, "Bad device admin requested for user=" + userHandle + ": " + adminName,
1289 e);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001290 return null;
1291 }
1292 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001293
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001294 private static JournaledFile makeJournaledFile(int userHandle) {
1295 final String base = userHandle == 0
1296 ? "/data/system/" + DEVICE_POLICIES_XML
1297 : new File(Environment.getUserSystemDirectory(userHandle), DEVICE_POLICIES_XML)
1298 .getAbsolutePath();
Dianne Hackbornd6847842010-01-12 18:14:19 -08001299 return new JournaledFile(new File(base), new File(base + ".tmp"));
1300 }
1301
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001302 private void saveSettingsLocked(int userHandle) {
1303 DevicePolicyData policy = getUserData(userHandle);
1304 JournaledFile journal = makeJournaledFile(userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001305 FileOutputStream stream = null;
1306 try {
1307 stream = new FileOutputStream(journal.chooseForWrite(), false);
1308 XmlSerializer out = new FastXmlSerializer();
1309 out.setOutput(stream, "utf-8");
1310 out.startDocument(null, true);
1311
1312 out.startTag(null, "policies");
Amith Yamasanif20d6402014-05-24 15:34:37 -07001313 if (policy.mRestrictionsProvider != null) {
1314 out.attribute(null, ATTR_PERMISSION_PROVIDER,
1315 policy.mRestrictionsProvider.flattenToString());
1316 }
Amith Yamasanied239cb2014-07-16 17:26:17 -07001317 if (policy.mUserSetupComplete) {
1318 out.attribute(null, ATTR_SETUP_COMPLETE,
1319 Boolean.toString(true));
1320 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001321
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001322 final int N = policy.mAdminList.size();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08001323 for (int i=0; i<N; i++) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001324 ActiveAdmin ap = policy.mAdminList.get(i);
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08001325 if (ap != null) {
1326 out.startTag(null, "admin");
1327 out.attribute(null, "name", ap.info.getComponent().flattenToString());
1328 ap.writeToXml(out);
1329 out.endTag(null, "admin");
1330 }
Dianne Hackbornd6847842010-01-12 18:14:19 -08001331 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001332
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001333 if (policy.mPasswordOwner >= 0) {
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08001334 out.startTag(null, "password-owner");
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001335 out.attribute(null, "value", Integer.toString(policy.mPasswordOwner));
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08001336 out.endTag(null, "password-owner");
1337 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001338
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001339 if (policy.mFailedPasswordAttempts != 0) {
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08001340 out.startTag(null, "failed-password-attempts");
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001341 out.attribute(null, "value", Integer.toString(policy.mFailedPasswordAttempts));
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08001342 out.endTag(null, "failed-password-attempts");
1343 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001344
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001345 if (policy.mActivePasswordQuality != 0 || policy.mActivePasswordLength != 0
1346 || policy.mActivePasswordUpperCase != 0 || policy.mActivePasswordLowerCase != 0
1347 || policy.mActivePasswordLetters != 0 || policy.mActivePasswordNumeric != 0
1348 || policy.mActivePasswordSymbols != 0 || policy.mActivePasswordNonLetter != 0) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001349 out.startTag(null, "active-password");
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001350 out.attribute(null, "quality", Integer.toString(policy.mActivePasswordQuality));
1351 out.attribute(null, "length", Integer.toString(policy.mActivePasswordLength));
1352 out.attribute(null, "uppercase", Integer.toString(policy.mActivePasswordUpperCase));
1353 out.attribute(null, "lowercase", Integer.toString(policy.mActivePasswordLowerCase));
1354 out.attribute(null, "letters", Integer.toString(policy.mActivePasswordLetters));
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07001355 out.attribute(null, "numeric", Integer
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001356 .toString(policy.mActivePasswordNumeric));
1357 out.attribute(null, "symbols", Integer.toString(policy.mActivePasswordSymbols));
1358 out.attribute(null, "nonletter", Integer.toString(policy.mActivePasswordNonLetter));
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001359 out.endTag(null, "active-password");
1360 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001361
Jason Monkd7b86212014-06-16 13:15:38 -04001362 for (int i=0; i<policy.mLockTaskPackages.size(); i++) {
1363 String component = policy.mLockTaskPackages.get(i);
justinzhang511e0d82014-03-24 16:09:24 -04001364 out.startTag(null, LOCK_TASK_COMPONENTS_XML);
Jason Monkd7b86212014-06-16 13:15:38 -04001365 out.attribute(null, "name", component);
justinzhang511e0d82014-03-24 16:09:24 -04001366 out.endTag(null, LOCK_TASK_COMPONENTS_XML);
1367 }
1368
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001369 out.endTag(null, "policies");
1370
Dianne Hackbornd6847842010-01-12 18:14:19 -08001371 out.endDocument();
Kenny Guy212037f2015-01-15 18:14:46 +00001372 stream.flush();
1373 FileUtils.sync(stream);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001374 stream.close();
1375 journal.commit();
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001376 sendChangedNotification(userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001377 } catch (IOException e) {
1378 try {
1379 if (stream != null) {
1380 stream.close();
1381 }
1382 } catch (IOException ex) {
1383 // Ignore
1384 }
1385 journal.rollback();
1386 }
1387 }
1388
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001389 private void sendChangedNotification(int userHandle) {
Jim Miller284b62e2010-06-08 14:27:42 -07001390 Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
1391 intent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Amith Yamasanib7a68592012-09-10 10:24:36 -07001392 long ident = Binder.clearCallingIdentity();
1393 try {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001394 mContext.sendBroadcastAsUser(intent, new UserHandle(userHandle));
Amith Yamasanib7a68592012-09-10 10:24:36 -07001395 } finally {
1396 Binder.restoreCallingIdentity(ident);
1397 }
Jim Miller284b62e2010-06-08 14:27:42 -07001398 }
1399
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001400 private void loadSettingsLocked(DevicePolicyData policy, int userHandle) {
1401 JournaledFile journal = makeJournaledFile(userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001402 FileInputStream stream = null;
1403 File file = journal.chooseForRead();
Dianne Hackbornd6847842010-01-12 18:14:19 -08001404 try {
1405 stream = new FileInputStream(file);
1406 XmlPullParser parser = Xml.newPullParser();
1407 parser.setInput(stream, null);
1408
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08001409 int type;
1410 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1411 && type != XmlPullParser.START_TAG) {
Dianne Hackbornd6847842010-01-12 18:14:19 -08001412 }
1413 String tag = parser.getName();
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08001414 if (!"policies".equals(tag)) {
1415 throw new XmlPullParserException(
1416 "Settings do not start with policies tag: found " + tag);
1417 }
Amith Yamasanif20d6402014-05-24 15:34:37 -07001418
1419 // Extract the permission provider component name if available
1420 String permissionProvider = parser.getAttributeValue(null, ATTR_PERMISSION_PROVIDER);
1421 if (permissionProvider != null) {
1422 policy.mRestrictionsProvider = ComponentName.unflattenFromString(permissionProvider);
1423 }
Amith Yamasanied239cb2014-07-16 17:26:17 -07001424 String userSetupComplete = parser.getAttributeValue(null, ATTR_SETUP_COMPLETE);
1425 if (userSetupComplete != null && Boolean.toString(true).equals(userSetupComplete)) {
1426 policy.mUserSetupComplete = true;
1427 }
Amith Yamasanif20d6402014-05-24 15:34:37 -07001428
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08001429 type = parser.next();
1430 int outerDepth = parser.getDepth();
Jason Monkd7b86212014-06-16 13:15:38 -04001431 policy.mLockTaskPackages.clear();
Robin Lee9c2be6c2014-07-22 16:47:40 +01001432 policy.mAdminList.clear();
1433 policy.mAdminMap.clear();
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08001434 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
1435 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1436 if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1437 continue;
1438 }
1439 tag = parser.getName();
1440 if ("admin".equals(tag)) {
Dianne Hackborne83cefc2010-02-04 17:38:14 -08001441 String name = parser.getAttributeValue(null, "name");
1442 try {
1443 DeviceAdminInfo dai = findAdmin(
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001444 ComponentName.unflattenFromString(name), userHandle);
1445 if (DBG && (UserHandle.getUserId(dai.getActivityInfo().applicationInfo.uid)
1446 != userHandle)) {
Amith Yamasanief38a102013-12-13 09:05:26 -08001447 Slog.w(LOG_TAG, "findAdmin returned an incorrect uid "
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001448 + dai.getActivityInfo().applicationInfo.uid + " for user "
1449 + userHandle);
1450 }
Dianne Hackborne83cefc2010-02-04 17:38:14 -08001451 if (dai != null) {
1452 ActiveAdmin ap = new ActiveAdmin(dai);
1453 ap.readFromXml(parser);
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001454 policy.mAdminMap.put(ap.info.getComponent(), ap);
Dianne Hackborne83cefc2010-02-04 17:38:14 -08001455 }
1456 } catch (RuntimeException e) {
Amith Yamasanief38a102013-12-13 09:05:26 -08001457 Slog.w(LOG_TAG, "Failed loading admin " + name, e);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001458 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08001459 } else if ("failed-password-attempts".equals(tag)) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001460 policy.mFailedPasswordAttempts = Integer.parseInt(
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08001461 parser.getAttributeValue(null, "value"));
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001462 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08001463 } else if ("password-owner".equals(tag)) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001464 policy.mPasswordOwner = Integer.parseInt(
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08001465 parser.getAttributeValue(null, "value"));
1466 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001467 } else if ("active-password".equals(tag)) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001468 policy.mActivePasswordQuality = Integer.parseInt(
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001469 parser.getAttributeValue(null, "quality"));
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001470 policy.mActivePasswordLength = Integer.parseInt(
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001471 parser.getAttributeValue(null, "length"));
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001472 policy.mActivePasswordUpperCase = Integer.parseInt(
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07001473 parser.getAttributeValue(null, "uppercase"));
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001474 policy.mActivePasswordLowerCase = Integer.parseInt(
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07001475 parser.getAttributeValue(null, "lowercase"));
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001476 policy.mActivePasswordLetters = Integer.parseInt(
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07001477 parser.getAttributeValue(null, "letters"));
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001478 policy.mActivePasswordNumeric = Integer.parseInt(
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07001479 parser.getAttributeValue(null, "numeric"));
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001480 policy.mActivePasswordSymbols = Integer.parseInt(
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07001481 parser.getAttributeValue(null, "symbols"));
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001482 policy.mActivePasswordNonLetter = Integer.parseInt(
Konstantin Lopyrevc8577402010-06-04 17:15:02 -07001483 parser.getAttributeValue(null, "nonletter"));
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001484 XmlUtils.skipCurrentTag(parser);
justinzhang511e0d82014-03-24 16:09:24 -04001485 } else if (LOCK_TASK_COMPONENTS_XML.equals(tag)) {
Jason Monkd7b86212014-06-16 13:15:38 -04001486 policy.mLockTaskPackages.add(parser.getAttributeValue(null, "name"));
justinzhang511e0d82014-03-24 16:09:24 -04001487 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001488 } else {
Amith Yamasanief38a102013-12-13 09:05:26 -08001489 Slog.w(LOG_TAG, "Unknown tag: " + tag);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001490 XmlUtils.skipCurrentTag(parser);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08001491 }
Dianne Hackbornd6847842010-01-12 18:14:19 -08001492 }
1493 } catch (NullPointerException e) {
Amith Yamasanief38a102013-12-13 09:05:26 -08001494 Slog.w(LOG_TAG, "failed parsing " + file + " " + e);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001495 } catch (NumberFormatException e) {
Amith Yamasanief38a102013-12-13 09:05:26 -08001496 Slog.w(LOG_TAG, "failed parsing " + file + " " + e);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001497 } catch (XmlPullParserException e) {
Amith Yamasanief38a102013-12-13 09:05:26 -08001498 Slog.w(LOG_TAG, "failed parsing " + file + " " + e);
Dianne Hackborncef65ee2010-09-30 18:27:22 -07001499 } catch (FileNotFoundException e) {
1500 // Don't be noisy, this is normal if we haven't defined any policies.
Dianne Hackbornd6847842010-01-12 18:14:19 -08001501 } catch (IOException e) {
Amith Yamasanief38a102013-12-13 09:05:26 -08001502 Slog.w(LOG_TAG, "failed parsing " + file + " " + e);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001503 } catch (IndexOutOfBoundsException e) {
Amith Yamasanief38a102013-12-13 09:05:26 -08001504 Slog.w(LOG_TAG, "failed parsing " + file + " " + e);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001505 }
1506 try {
1507 if (stream != null) {
1508 stream.close();
1509 }
1510 } catch (IOException e) {
1511 // Ignore
1512 }
1513
Robin Lee9c2be6c2014-07-22 16:47:40 +01001514 // Generate a list of admins from the admin map
1515 policy.mAdminList.addAll(policy.mAdminMap.values());
1516
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001517 // Validate that what we stored for the password quality matches
1518 // sufficiently what is currently set. Note that this is only
1519 // a sanity check in case the two get out of sync; this should
1520 // never normally happen.
1521 LockPatternUtils utils = new LockPatternUtils(mContext);
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001522 if (utils.getActivePasswordQuality() < policy.mActivePasswordQuality) {
Amith Yamasanief38a102013-12-13 09:05:26 -08001523 Slog.w(LOG_TAG, "Active password quality 0x"
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001524 + Integer.toHexString(policy.mActivePasswordQuality)
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001525 + " does not match actual quality 0x"
1526 + Integer.toHexString(utils.getActivePasswordQuality()));
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001527 policy.mActivePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
1528 policy.mActivePasswordLength = 0;
1529 policy.mActivePasswordUpperCase = 0;
1530 policy.mActivePasswordLowerCase = 0;
1531 policy.mActivePasswordLetters = 0;
1532 policy.mActivePasswordNumeric = 0;
1533 policy.mActivePasswordSymbols = 0;
1534 policy.mActivePasswordNonLetter = 0;
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001535 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001536
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001537 validatePasswordOwnerLocked(policy);
1538 syncDeviceCapabilitiesLocked(policy);
1539 updateMaximumTimeToLockLocked(policy);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001540 }
1541
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001542 static void validateQualityConstant(int quality) {
1543 switch (quality) {
1544 case DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED:
Danielle Millettde7a2f32011-12-21 17:02:32 -05001545 case DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK:
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001546 case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
1547 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
Jim Miller85516d02014-01-31 17:08:37 -08001548 case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001549 case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
1550 case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07001551 case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001552 return;
1553 }
1554 throw new IllegalArgumentException("Invalid quality constant: 0x"
1555 + Integer.toHexString(quality));
1556 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001557
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001558 void validatePasswordOwnerLocked(DevicePolicyData policy) {
1559 if (policy.mPasswordOwner >= 0) {
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08001560 boolean haveOwner = false;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001561 for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
1562 if (policy.mAdminList.get(i).getUid() == policy.mPasswordOwner) {
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08001563 haveOwner = true;
1564 break;
1565 }
1566 }
1567 if (!haveOwner) {
Amith Yamasanief38a102013-12-13 09:05:26 -08001568 Slog.w(LOG_TAG, "Previous password owner " + policy.mPasswordOwner
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08001569 + " no longer active; disabling");
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001570 policy.mPasswordOwner = -1;
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08001571 }
1572 }
1573 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001574
Ben Komalo2447edd2011-05-09 16:05:33 -07001575 /**
1576 * Pushes down policy information to the system for any policies related to general device
1577 * capabilities that need to be enforced by lower level services (e.g. Camera services).
1578 */
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001579 void syncDeviceCapabilitiesLocked(DevicePolicyData policy) {
Ben Komalo2447edd2011-05-09 16:05:33 -07001580 // Ensure the status of the camera is synced down to the system. Interested native services
1581 // should monitor this value and act accordingly.
1582 boolean systemState = SystemProperties.getBoolean(SYSTEM_PROP_DISABLE_CAMERA, false);
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001583 boolean cameraDisabled = getCameraDisabled(null, policy.mUserHandle);
Ben Komalo2447edd2011-05-09 16:05:33 -07001584 if (cameraDisabled != systemState) {
1585 long token = Binder.clearCallingIdentity();
1586 try {
1587 String value = cameraDisabled ? "1" : "0";
Amith Yamasanief38a102013-12-13 09:05:26 -08001588 if (DBG) Slog.v(LOG_TAG, "Change in camera state ["
Ben Komalo2447edd2011-05-09 16:05:33 -07001589 + SYSTEM_PROP_DISABLE_CAMERA + "] = " + value);
1590 SystemProperties.set(SYSTEM_PROP_DISABLE_CAMERA, value);
1591 } finally {
1592 Binder.restoreCallingIdentity(token);
1593 }
1594 }
1595 }
1596
Dianne Hackbornd6847842010-01-12 18:14:19 -08001597 public void systemReady() {
Amith Yamasani44a01b72013-09-16 10:44:57 -07001598 if (!mHasFeature) {
1599 return;
1600 }
Robin Lee9c2be6c2014-07-22 16:47:40 +01001601 getUserData(UserHandle.USER_OWNER);
1602 loadDeviceOwner();
Alexandra Gherghina22745f42014-06-04 12:03:08 +01001603 cleanUpOldUsers();
Amith Yamasanied239cb2014-07-16 17:26:17 -07001604 // Register an observer for watching for user setup complete.
1605 new SetupContentObserver(mHandler).register(mContext.getContentResolver());
1606 // Initialize the user setup state, to handle the upgrade case.
1607 updateUserSetupComplete();
Sander Alewijnsea87863a2014-07-29 12:01:38 +01001608
1609 // Update the screen capture disabled cache in the window manager
1610 List<UserInfo> users = mUserManager.getUsers(true);
1611 final int N = users.size();
1612 for (int i = 0; i < N; i++) {
1613 int userHandle = users.get(i).id;
1614 updateScreenCaptureDisabledInWindowManager(userHandle,
1615 getScreenCaptureDisabled(null, userHandle));
1616 }
1617
Dianne Hackbornd6847842010-01-12 18:14:19 -08001618 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001619
Alexandra Gherghina22745f42014-06-04 12:03:08 +01001620 private void cleanUpOldUsers() {
1621 // This is needed in case the broadcast {@link Intent.ACTION_USER_REMOVED} was not handled
1622 // before reboot
1623 Set<Integer> usersWithProfileOwners;
1624 Set<Integer> usersWithData;
1625 synchronized(this) {
1626 usersWithProfileOwners = mDeviceOwner != null
1627 ? mDeviceOwner.getProfileOwnerKeys() : new HashSet<Integer>();
1628 usersWithData = new HashSet<Integer>();
1629 for (int i = 0; i < mUserData.size(); i++) {
1630 usersWithData.add(mUserData.keyAt(i));
1631 }
1632 }
1633 List<UserInfo> allUsers = mUserManager.getUsers();
1634
1635 Set<Integer> deletedUsers = new HashSet<Integer>();
1636 deletedUsers.addAll(usersWithProfileOwners);
1637 deletedUsers.addAll(usersWithData);
1638 for (UserInfo userInfo : allUsers) {
1639 deletedUsers.remove(userInfo.id);
1640 }
1641 for (Integer userId : deletedUsers) {
1642 removeUserData(userId);
1643 }
1644 }
1645
Jessica Hummel91da58d2014-04-10 17:39:43 +01001646 private void handlePasswordExpirationNotification(int userHandle) {
Jim Millera4e28d12010-11-08 16:15:47 -08001647 synchronized (this) {
1648 final long now = System.currentTimeMillis();
Jessica Hummel91da58d2014-04-10 17:39:43 +01001649
1650 List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
1651 for (UserInfo ui : profiles) {
Jim Millere303bf42014-08-26 17:12:29 -07001652 int profileUserHandle = ui.id;
Jessica Hummel91da58d2014-04-10 17:39:43 +01001653 final DevicePolicyData policy = getUserData(profileUserHandle);
1654 final int count = policy.mAdminList.size();
1655 if (count > 0) {
1656 for (int i = 0; i < count; i++) {
1657 final ActiveAdmin admin = policy.mAdminList.get(i);
1658 if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)
1659 && admin.passwordExpirationTimeout > 0L
1660 && now >= admin.passwordExpirationDate - EXPIRATION_GRACE_PERIOD_MS
1661 && admin.passwordExpirationDate > 0L) {
1662 sendAdminCommandLocked(admin,
1663 DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING);
1664 }
1665 }
Jim Millera4e28d12010-11-08 16:15:47 -08001666 }
1667 }
Jessica Hummel91da58d2014-04-10 17:39:43 +01001668 setExpirationAlarmCheckLocked(mContext, getUserData(userHandle));
Jim Millera4e28d12010-11-08 16:15:47 -08001669 }
1670 }
1671
Robin Leed0130e82014-10-06 11:36:25 +01001672 private class MonitoringCertNotificationTask extends AsyncTask<Intent, Void, Void> {
1673 @Override
1674 protected Void doInBackground(Intent... params) {
1675 int userHandle = params[0].getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_ALL);
Maggie Benthall0469f412013-09-05 15:30:26 -04001676
Robin Leed0130e82014-10-06 11:36:25 +01001677 if (userHandle == UserHandle.USER_ALL) {
1678 for (UserInfo userInfo : mUserManager.getUsers()) {
1679 manageNotification(userInfo.getUserHandle());
Maggie Benthall0469f412013-09-05 15:30:26 -04001680 }
Robin Leed0130e82014-10-06 11:36:25 +01001681 } else {
1682 manageNotification(new UserHandle(userHandle));
Maggie Benthall0469f412013-09-05 15:30:26 -04001683 }
Robin Leed0130e82014-10-06 11:36:25 +01001684 return null;
Maggie Benthall0469f412013-09-05 15:30:26 -04001685 }
1686
Robin Leed0130e82014-10-06 11:36:25 +01001687 private void manageNotification(UserHandle userHandle) {
1688 if (!mUserManager.isUserRunning(userHandle)) {
1689 return;
Maggie Benthall0469f412013-09-05 15:30:26 -04001690 }
Robin Leed0130e82014-10-06 11:36:25 +01001691
Robin Lee80559f42014-11-25 13:40:49 +00001692 // Call out to KeyChain to check for user-added CAs
Robin Leed0130e82014-10-06 11:36:25 +01001693 boolean hasCert = false;
Robin Leed0130e82014-10-06 11:36:25 +01001694 try {
1695 KeyChainConnection kcs = KeyChain.bindAsUser(mContext, userHandle);
1696 try {
1697 if (!kcs.getService().getUserCaAliases().getList().isEmpty()) {
1698 hasCert = true;
1699 }
1700 } catch (RemoteException e) {
1701 Log.e(LOG_TAG, "Could not connect to KeyChain service", e);
1702 } finally {
1703 kcs.close();
1704 }
1705 } catch (InterruptedException e) {
1706 Thread.currentThread().interrupt();
1707 } catch (RuntimeException e) {
1708 Log.e(LOG_TAG, "Could not connect to KeyChain service", e);
Robin Leed0130e82014-10-06 11:36:25 +01001709 }
1710 if (!hasCert) {
1711 getNotificationManager().cancelAsUser(
1712 null, MONITORING_CERT_NOTIFICATION_ID, userHandle);
1713 return;
1714 }
1715
Robin Lee80559f42014-11-25 13:40:49 +00001716 // Build and show a warning notification
Robin Leed0130e82014-10-06 11:36:25 +01001717 int smallIconId;
1718 String contentText;
1719 final String ownerName = getDeviceOwnerName();
Robin Lee7f7ea822015-01-08 22:46:44 +00001720 if (isManagedProfile(userHandle.getIdentifier())) {
1721 contentText = mContext.getString(R.string.ssl_ca_cert_noti_by_administrator);
1722 smallIconId = R.drawable.stat_sys_certificate_info;
1723 } else if (ownerName != null) {
Robin Leed0130e82014-10-06 11:36:25 +01001724 contentText = mContext.getString(R.string.ssl_ca_cert_noti_managed, ownerName);
1725 smallIconId = R.drawable.stat_sys_certificate_info;
1726 } else {
1727 contentText = mContext.getString(R.string.ssl_ca_cert_noti_by_unknown);
1728 smallIconId = android.R.drawable.stat_sys_warning;
1729 }
1730
1731 Intent dialogIntent = new Intent(Settings.ACTION_MONITORING_CERT_INFO);
1732 dialogIntent.setFlags(
1733 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1734 dialogIntent.setPackage("com.android.settings");
1735 PendingIntent notifyIntent = PendingIntent.getActivityAsUser(mContext, 0,
1736 dialogIntent, PendingIntent.FLAG_UPDATE_CURRENT, null, userHandle);
1737
1738 final Context userContext;
1739 try {
1740 userContext = mContext.createPackageContextAsUser("android", 0, userHandle);
1741 } catch (PackageManager.NameNotFoundException e) {
1742 Log.e(LOG_TAG, "Create context as " + userHandle + " failed", e);
1743 return;
1744 }
1745 final Notification noti = new Notification.Builder(userContext)
1746 .setSmallIcon(smallIconId)
1747 .setContentTitle(mContext.getString(R.string.ssl_ca_cert_warning))
1748 .setContentText(contentText)
1749 .setContentIntent(notifyIntent)
Robin Leed0130e82014-10-06 11:36:25 +01001750 .setPriority(Notification.PRIORITY_HIGH)
1751 .setShowWhen(false)
1752 .setColor(mContext.getResources().getColor(
1753 com.android.internal.R.color.system_notification_accent_color))
1754 .build();
1755
1756 getNotificationManager().notifyAsUser(
1757 null, MONITORING_CERT_NOTIFICATION_ID, noti, userHandle);
Maggie Benthall0469f412013-09-05 15:30:26 -04001758 }
1759 }
1760
Andy Stadlerc25f70a2010-12-08 15:56:45 -08001761 /**
1762 * @param adminReceiver The admin to add
1763 * @param refreshing true = update an active admin, no error
1764 */
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001765 public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07001766 if (!mHasFeature) {
1767 return;
1768 }
Jason Monk03978a42014-06-10 15:05:30 -04001769 setActiveAdmin(adminReceiver, refreshing, userHandle, null);
1770 }
1771
1772 private void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle,
1773 Bundle onEnableData) {
Dianne Hackbornd6847842010-01-12 18:14:19 -08001774 mContext.enforceCallingOrSelfPermission(
Amith Yamasania418cf22013-07-19 12:39:17 -07001775 android.Manifest.permission.MANAGE_DEVICE_ADMINS, null);
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001776 enforceCrossUserPermission(userHandle);
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001777
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001778 DevicePolicyData policy = getUserData(userHandle);
1779 DeviceAdminInfo info = findAdmin(adminReceiver, userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001780 if (info == null) {
1781 throw new IllegalArgumentException("Bad admin: " + adminReceiver);
1782 }
1783 synchronized (this) {
1784 long ident = Binder.clearCallingIdentity();
1785 try {
Amith Yamasanief38a102013-12-13 09:05:26 -08001786 if (!refreshing
1787 && getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08001788 throw new IllegalArgumentException("Admin is already added");
Dianne Hackbornd6847842010-01-12 18:14:19 -08001789 }
Andy Stadlerc25f70a2010-12-08 15:56:45 -08001790 ActiveAdmin newAdmin = new ActiveAdmin(info);
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001791 policy.mAdminMap.put(adminReceiver, newAdmin);
Andy Stadlerc25f70a2010-12-08 15:56:45 -08001792 int replaceIndex = -1;
Robin Lee9c2be6c2014-07-22 16:47:40 +01001793 final int N = policy.mAdminList.size();
1794 for (int i=0; i < N; i++) {
1795 ActiveAdmin oldAdmin = policy.mAdminList.get(i);
1796 if (oldAdmin.info.getComponent().equals(adminReceiver)) {
1797 replaceIndex = i;
1798 break;
Andy Stadlerc25f70a2010-12-08 15:56:45 -08001799 }
1800 }
1801 if (replaceIndex == -1) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001802 policy.mAdminList.add(newAdmin);
Amith Yamasani71e6c692013-03-24 17:39:28 -07001803 enableIfNecessary(info.getPackageName(), userHandle);
Andy Stadlerc25f70a2010-12-08 15:56:45 -08001804 } else {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001805 policy.mAdminList.set(replaceIndex, newAdmin);
Andy Stadlerc25f70a2010-12-08 15:56:45 -08001806 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001807 saveSettingsLocked(userHandle);
Jason Monk03978a42014-06-10 15:05:30 -04001808 sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
1809 onEnableData, null);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001810 } finally {
1811 Binder.restoreCallingIdentity(ident);
1812 }
1813 }
1814 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001815
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001816 public boolean isAdminActive(ComponentName adminReceiver, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07001817 if (!mHasFeature) {
1818 return false;
1819 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001820 enforceCrossUserPermission(userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001821 synchronized (this) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001822 return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null;
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08001823 }
1824 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001825
Fyodor Kupolov96fb9322014-12-01 15:08:09 -08001826 @Override
1827 public boolean isRemovingAdmin(ComponentName adminReceiver, int userHandle) {
1828 if (!mHasFeature) {
1829 return false;
1830 }
1831 enforceCrossUserPermission(userHandle);
1832 synchronized (this) {
1833 DevicePolicyData policyData = getUserData(userHandle);
1834 return policyData.mRemovingAdmins.contains(adminReceiver);
1835 }
1836 }
1837
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001838 public boolean hasGrantedPolicy(ComponentName adminReceiver, int policyId, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07001839 if (!mHasFeature) {
1840 return false;
1841 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001842 enforceCrossUserPermission(userHandle);
Andy Stadlerc25f70a2010-12-08 15:56:45 -08001843 synchronized (this) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001844 ActiveAdmin administrator = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
Andy Stadlerc25f70a2010-12-08 15:56:45 -08001845 if (administrator == null) {
1846 throw new SecurityException("No active admin " + adminReceiver);
1847 }
1848 return administrator.info.usesPolicy(policyId);
1849 }
1850 }
1851
Amith Yamasani44a01b72013-09-16 10:44:57 -07001852 @SuppressWarnings("unchecked")
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001853 public List<ComponentName> getActiveAdmins(int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07001854 if (!mHasFeature) {
1855 return Collections.EMPTY_LIST;
1856 }
1857
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001858 enforceCrossUserPermission(userHandle);
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08001859 synchronized (this) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001860 DevicePolicyData policy = getUserData(userHandle);
1861 final int N = policy.mAdminList.size();
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08001862 if (N <= 0) {
1863 return null;
1864 }
1865 ArrayList<ComponentName> res = new ArrayList<ComponentName>(N);
1866 for (int i=0; i<N; i++) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001867 res.add(policy.mAdminList.get(i).info.getComponent());
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08001868 }
1869 return res;
Dianne Hackbornd6847842010-01-12 18:14:19 -08001870 }
1871 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001872
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001873 public boolean packageHasActiveAdmins(String packageName, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07001874 if (!mHasFeature) {
1875 return false;
1876 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001877 enforceCrossUserPermission(userHandle);
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001878 synchronized (this) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001879 DevicePolicyData policy = getUserData(userHandle);
1880 final int N = policy.mAdminList.size();
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001881 for (int i=0; i<N; i++) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001882 if (policy.mAdminList.get(i).info.getPackageName().equals(packageName)) {
Dianne Hackborn21f1bd12010-02-19 17:02:21 -08001883 return true;
1884 }
1885 }
1886 return false;
1887 }
1888 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001889
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001890 public void removeActiveAdmin(ComponentName adminReceiver, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07001891 if (!mHasFeature) {
1892 return;
1893 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001894 enforceCrossUserPermission(userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001895 synchronized (this) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001896 ActiveAdmin admin = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08001897 if (admin == null) {
1898 return;
1899 }
1900 if (admin.getUid() != Binder.getCallingUid()) {
Amith Yamasani71e6c692013-03-24 17:39:28 -07001901 // If trying to remove device owner, refuse when the caller is not the owner.
Robin Lee08fc72d2014-02-20 12:50:41 +00001902 if (isDeviceOwner(adminReceiver.getPackageName())) {
Amith Yamasani71e6c692013-03-24 17:39:28 -07001903 return;
1904 }
Dianne Hackbornd6847842010-01-12 18:14:19 -08001905 mContext.enforceCallingOrSelfPermission(
Amith Yamasania418cf22013-07-19 12:39:17 -07001906 android.Manifest.permission.MANAGE_DEVICE_ADMINS, null);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001907 }
1908 long ident = Binder.clearCallingIdentity();
1909 try {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001910 removeActiveAdminLocked(adminReceiver, userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001911 } finally {
1912 Binder.restoreCallingIdentity(ident);
1913 }
1914 }
1915 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001916
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001917 public void setPasswordQuality(ComponentName who, int quality, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07001918 if (!mHasFeature) {
1919 return;
1920 }
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001921 validateQualityConstant(quality);
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001922 enforceCrossUserPermission(userHandle);
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001923
Dianne Hackbornd6847842010-01-12 18:14:19 -08001924 synchronized (this) {
1925 if (who == null) {
1926 throw new NullPointerException("ComponentName is null");
1927 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08001928 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
1929 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07001930 if (ap.passwordQuality != quality) {
1931 ap.passwordQuality = quality;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001932 saveSettingsLocked(userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001933 }
1934 }
1935 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001936
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001937 public int getPasswordQuality(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07001938 if (!mHasFeature) {
1939 return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
1940 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001941 enforceCrossUserPermission(userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001942 synchronized (this) {
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08001943 int mode = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001944
Dianne Hackborn254cb442010-01-27 19:23:59 -08001945 if (who != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001946 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08001947 return admin != null ? admin.passwordQuality : mode;
Dianne Hackborn254cb442010-01-27 19:23:59 -08001948 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001949
Jessica Hummel91da58d2014-04-10 17:39:43 +01001950 // Return strictest policy for this user and profiles that are visible from this user.
1951 List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
1952 for (UserInfo userInfo : profiles) {
Benjamin Franzfadb2b32015-01-14 18:22:42 +00001953 DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
Jessica Hummel91da58d2014-04-10 17:39:43 +01001954 final int N = policy.mAdminList.size();
1955 for (int i=0; i<N; i++) {
1956 ActiveAdmin admin = policy.mAdminList.get(i);
1957 if (mode < admin.passwordQuality) {
1958 mode = admin.passwordQuality;
1959 }
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08001960 }
1961 }
1962 return mode;
Dianne Hackbornd6847842010-01-12 18:14:19 -08001963 }
1964 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001965
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001966 public void setPasswordMinimumLength(ComponentName who, int length, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07001967 if (!mHasFeature) {
1968 return;
1969 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001970 enforceCrossUserPermission(userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001971 synchronized (this) {
1972 if (who == null) {
1973 throw new NullPointerException("ComponentName is null");
1974 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08001975 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
1976 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001977 if (ap.minimumPasswordLength != length) {
1978 ap.minimumPasswordLength = length;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001979 saveSettingsLocked(userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001980 }
1981 }
1982 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001983
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001984 public int getPasswordMinimumLength(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07001985 if (!mHasFeature) {
1986 return 0;
1987 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001988 enforceCrossUserPermission(userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08001989 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08001990 int length = 0;
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001991
Dianne Hackborn254cb442010-01-27 19:23:59 -08001992 if (who != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07001993 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
Dianne Hackborn254cb442010-01-27 19:23:59 -08001994 return admin != null ? admin.minimumPasswordLength : length;
1995 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07001996
Jessica Hummel91da58d2014-04-10 17:39:43 +01001997 // Return strictest policy for this user and profiles that are visible from this user.
1998 List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
1999 for (UserInfo userInfo : profiles) {
Benjamin Franzfadb2b32015-01-14 18:22:42 +00002000 DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002001 final int N = policy.mAdminList.size();
2002 for (int i=0; i<N; i++) {
2003 ActiveAdmin admin = policy.mAdminList.get(i);
2004 if (length < admin.minimumPasswordLength) {
2005 length = admin.minimumPasswordLength;
2006 }
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08002007 }
2008 }
2009 return length;
Dianne Hackbornd6847842010-01-12 18:14:19 -08002010 }
2011 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002012
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002013 public void setPasswordHistoryLength(ComponentName who, int length, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002014 if (!mHasFeature) {
2015 return;
2016 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002017 enforceCrossUserPermission(userHandle);
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002018 synchronized (this) {
2019 if (who == null) {
2020 throw new NullPointerException("ComponentName is null");
2021 }
2022 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
2023 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
2024 if (ap.passwordHistoryLength != length) {
2025 ap.passwordHistoryLength = length;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002026 saveSettingsLocked(userHandle);
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002027 }
2028 }
2029 }
2030
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002031 public int getPasswordHistoryLength(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002032 if (!mHasFeature) {
2033 return 0;
2034 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002035 enforceCrossUserPermission(userHandle);
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002036 synchronized (this) {
2037 int length = 0;
2038
2039 if (who != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002040 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002041 return admin != null ? admin.passwordHistoryLength : length;
2042 }
2043
Jessica Hummel91da58d2014-04-10 17:39:43 +01002044 // Return strictest policy for this user and profiles that are visible from this user.
2045 List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
2046 for (UserInfo userInfo : profiles) {
Benjamin Franzfadb2b32015-01-14 18:22:42 +00002047 DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002048 final int N = policy.mAdminList.size();
2049 for (int i = 0; i < N; i++) {
2050 ActiveAdmin admin = policy.mAdminList.get(i);
2051 if (length < admin.passwordHistoryLength) {
2052 length = admin.passwordHistoryLength;
2053 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002054 }
2055 }
2056 return length;
2057 }
2058 }
2059
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002060 public void setPasswordExpirationTimeout(ComponentName who, long timeout, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002061 if (!mHasFeature) {
2062 return;
2063 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002064 enforceCrossUserPermission(userHandle);
Jim Millera4e28d12010-11-08 16:15:47 -08002065 synchronized (this) {
2066 if (who == null) {
2067 throw new NullPointerException("ComponentName is null");
2068 }
Andy Stadler1f35d482010-11-19 15:39:41 -08002069 if (timeout < 0) {
2070 throw new IllegalArgumentException("Timeout must be >= 0 ms");
Jim Millera4e28d12010-11-08 16:15:47 -08002071 }
2072 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
2073 DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD);
2074 // Calling this API automatically bumps the expiration date
2075 final long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L;
2076 ap.passwordExpirationDate = expiration;
2077 ap.passwordExpirationTimeout = timeout;
2078 if (timeout > 0L) {
Amith Yamasanief38a102013-12-13 09:05:26 -08002079 Slog.w(LOG_TAG, "setPasswordExpiration(): password will expire on "
Jim Millera4e28d12010-11-08 16:15:47 -08002080 + DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)
2081 .format(new Date(expiration)));
2082 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002083 saveSettingsLocked(userHandle);
2084 // in case this is the first one
2085 setExpirationAlarmCheckLocked(mContext, getUserData(userHandle));
Jim Millera4e28d12010-11-08 16:15:47 -08002086 }
2087 }
2088
Andy Stadler043116a2010-11-29 17:43:32 -08002089 /**
2090 * Return a single admin's expiration cycle time, or the min of all cycle times.
2091 * Returns 0 if not configured.
2092 */
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002093 public long getPasswordExpirationTimeout(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002094 if (!mHasFeature) {
2095 return 0L;
2096 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002097 enforceCrossUserPermission(userHandle);
Jim Millera4e28d12010-11-08 16:15:47 -08002098 synchronized (this) {
Jessica Hummel91da58d2014-04-10 17:39:43 +01002099 long timeout = 0L;
2100
Jim Millera4e28d12010-11-08 16:15:47 -08002101 if (who != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002102 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002103 return admin != null ? admin.passwordExpirationTimeout : timeout;
Jim Millera4e28d12010-11-08 16:15:47 -08002104 }
2105
Jessica Hummel91da58d2014-04-10 17:39:43 +01002106 List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
2107 for (UserInfo userInfo : profiles) {
Benjamin Franzfadb2b32015-01-14 18:22:42 +00002108 DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002109 final int N = policy.mAdminList.size();
2110 for (int i = 0; i < N; i++) {
2111 ActiveAdmin admin = policy.mAdminList.get(i);
2112 if (timeout == 0L || (admin.passwordExpirationTimeout != 0L
2113 && timeout > admin.passwordExpirationTimeout)) {
2114 timeout = admin.passwordExpirationTimeout;
2115 }
Jim Millera4e28d12010-11-08 16:15:47 -08002116 }
2117 }
2118 return timeout;
2119 }
2120 }
2121
Svetoslav976e8bd2014-07-16 15:12:03 -07002122 @Override
2123 public boolean addCrossProfileWidgetProvider(ComponentName admin, String packageName) {
Svet Ganov6bd70252014-08-20 09:47:47 -07002124 final int userId = UserHandle.getCallingUserId();
2125 List<String> changedProviders = null;
2126
2127 synchronized (this) {
2128 ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
2129 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
2130 if (activeAdmin.crossProfileWidgetProviders == null) {
2131 activeAdmin.crossProfileWidgetProviders = new ArrayList<>();
2132 }
2133 List<String> providers = activeAdmin.crossProfileWidgetProviders;
2134 if (!providers.contains(packageName)) {
2135 providers.add(packageName);
2136 changedProviders = new ArrayList<>(providers);
2137 saveSettingsLocked(userId);
2138 }
Svetoslav976e8bd2014-07-16 15:12:03 -07002139 }
Svet Ganov6bd70252014-08-20 09:47:47 -07002140
2141 if (changedProviders != null) {
2142 mLocalService.notifyCrossProfileProvidersChanged(userId, changedProviders);
Svetoslav976e8bd2014-07-16 15:12:03 -07002143 return true;
2144 }
Svet Ganov6bd70252014-08-20 09:47:47 -07002145
Svetoslav976e8bd2014-07-16 15:12:03 -07002146 return false;
2147 }
2148
2149 @Override
2150 public boolean removeCrossProfileWidgetProvider(ComponentName admin, String packageName) {
Svet Ganov6bd70252014-08-20 09:47:47 -07002151 final int userId = UserHandle.getCallingUserId();
2152 List<String> changedProviders = null;
2153
2154 synchronized (this) {
2155 ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
2156 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
2157 if (activeAdmin.crossProfileWidgetProviders == null) {
2158 return false;
2159 }
2160 List<String> providers = activeAdmin.crossProfileWidgetProviders;
2161 if (providers.remove(packageName)) {
2162 changedProviders = new ArrayList<>(providers);
2163 saveSettingsLocked(userId);
2164 }
Svetoslav976e8bd2014-07-16 15:12:03 -07002165 }
Svet Ganov6bd70252014-08-20 09:47:47 -07002166
2167 if (changedProviders != null) {
2168 mLocalService.notifyCrossProfileProvidersChanged(userId, changedProviders);
Svetoslav976e8bd2014-07-16 15:12:03 -07002169 return true;
2170 }
Svet Ganov6bd70252014-08-20 09:47:47 -07002171
Svetoslav976e8bd2014-07-16 15:12:03 -07002172 return false;
2173 }
2174
2175 @Override
2176 public List<String> getCrossProfileWidgetProviders(ComponentName admin) {
Svet Ganov6bd70252014-08-20 09:47:47 -07002177 synchronized (this) {
2178 ActiveAdmin activeAdmin = getActiveAdminForCallerLocked(admin,
2179 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
2180 if (activeAdmin.crossProfileWidgetProviders == null
2181 || activeAdmin.crossProfileWidgetProviders.isEmpty()) {
2182 return null;
2183 }
2184 if (Binder.getCallingUid() == Process.myUid()) {
2185 return new ArrayList<>(activeAdmin.crossProfileWidgetProviders);
2186 } else {
2187 return activeAdmin.crossProfileWidgetProviders;
2188 }
Svetoslav976e8bd2014-07-16 15:12:03 -07002189 }
2190 }
2191
Andy Stadler043116a2010-11-29 17:43:32 -08002192 /**
2193 * Return a single admin's expiration date/time, or the min (soonest) for all admins.
2194 * Returns 0 if not configured.
2195 */
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002196 private long getPasswordExpirationLocked(ComponentName who, int userHandle) {
Jessica Hummel91da58d2014-04-10 17:39:43 +01002197 long timeout = 0L;
2198
Jim Millera4e28d12010-11-08 16:15:47 -08002199 if (who != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002200 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002201 return admin != null ? admin.passwordExpirationDate : timeout;
Jim Millera4e28d12010-11-08 16:15:47 -08002202 }
2203
Jessica Hummel91da58d2014-04-10 17:39:43 +01002204 List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
2205 for (UserInfo userInfo : profiles) {
Benjamin Franzfadb2b32015-01-14 18:22:42 +00002206 DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002207 final int N = policy.mAdminList.size();
2208 for (int i = 0; i < N; i++) {
2209 ActiveAdmin admin = policy.mAdminList.get(i);
2210 if (timeout == 0L || (admin.passwordExpirationDate != 0
2211 && timeout > admin.passwordExpirationDate)) {
2212 timeout = admin.passwordExpirationDate;
2213 }
Jim Millera4e28d12010-11-08 16:15:47 -08002214 }
2215 }
2216 return timeout;
2217 }
2218
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002219 public long getPasswordExpiration(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002220 if (!mHasFeature) {
2221 return 0L;
2222 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002223 enforceCrossUserPermission(userHandle);
Jim Millera4e28d12010-11-08 16:15:47 -08002224 synchronized (this) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002225 return getPasswordExpirationLocked(who, userHandle);
Jim Millera4e28d12010-11-08 16:15:47 -08002226 }
2227 }
2228
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002229 public void setPasswordMinimumUpperCase(ComponentName who, int length, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002230 if (!mHasFeature) {
2231 return;
2232 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002233 enforceCrossUserPermission(userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002234 synchronized (this) {
2235 if (who == null) {
2236 throw new NullPointerException("ComponentName is null");
2237 }
2238 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
2239 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
2240 if (ap.minimumPasswordUpperCase != length) {
2241 ap.minimumPasswordUpperCase = length;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002242 saveSettingsLocked(userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002243 }
2244 }
2245 }
2246
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002247 public int getPasswordMinimumUpperCase(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002248 if (!mHasFeature) {
2249 return 0;
2250 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002251 enforceCrossUserPermission(userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002252 synchronized (this) {
2253 int length = 0;
2254
2255 if (who != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002256 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002257 return admin != null ? admin.minimumPasswordUpperCase : length;
2258 }
2259
Jessica Hummel91da58d2014-04-10 17:39:43 +01002260 // Return strictest policy for this user and profiles that are visible from this user.
2261 List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
2262 for (UserInfo userInfo : profiles) {
Benjamin Franzfadb2b32015-01-14 18:22:42 +00002263 DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002264 final int N = policy.mAdminList.size();
2265 for (int i=0; i<N; i++) {
2266 ActiveAdmin admin = policy.mAdminList.get(i);
2267 if (length < admin.minimumPasswordUpperCase) {
2268 length = admin.minimumPasswordUpperCase;
2269 }
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002270 }
2271 }
2272 return length;
2273 }
2274 }
2275
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002276 public void setPasswordMinimumLowerCase(ComponentName who, int length, int userHandle) {
2277 enforceCrossUserPermission(userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002278 synchronized (this) {
2279 if (who == null) {
2280 throw new NullPointerException("ComponentName is null");
2281 }
2282 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
2283 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
2284 if (ap.minimumPasswordLowerCase != length) {
2285 ap.minimumPasswordLowerCase = length;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002286 saveSettingsLocked(userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002287 }
2288 }
2289 }
2290
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002291 public int getPasswordMinimumLowerCase(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002292 if (!mHasFeature) {
2293 return 0;
2294 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002295 enforceCrossUserPermission(userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002296 synchronized (this) {
2297 int length = 0;
2298
2299 if (who != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002300 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002301 return admin != null ? admin.minimumPasswordLowerCase : length;
2302 }
2303
Jessica Hummel91da58d2014-04-10 17:39:43 +01002304 // Return strictest policy for this user and profiles that are visible from this user.
2305 List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
2306 for (UserInfo userInfo : profiles) {
Benjamin Franzfadb2b32015-01-14 18:22:42 +00002307 DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002308 final int N = policy.mAdminList.size();
2309 for (int i=0; i<N; i++) {
2310 ActiveAdmin admin = policy.mAdminList.get(i);
2311 if (length < admin.minimumPasswordLowerCase) {
2312 length = admin.minimumPasswordLowerCase;
2313 }
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002314 }
2315 }
2316 return length;
2317 }
2318 }
2319
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002320 public void setPasswordMinimumLetters(ComponentName who, int length, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002321 if (!mHasFeature) {
2322 return;
2323 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002324 enforceCrossUserPermission(userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002325 synchronized (this) {
2326 if (who == null) {
2327 throw new NullPointerException("ComponentName is null");
2328 }
2329 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
2330 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
2331 if (ap.minimumPasswordLetters != length) {
2332 ap.minimumPasswordLetters = length;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002333 saveSettingsLocked(userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002334 }
2335 }
2336 }
2337
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002338 public int getPasswordMinimumLetters(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002339 if (!mHasFeature) {
2340 return 0;
2341 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002342 enforceCrossUserPermission(userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002343 synchronized (this) {
2344 int length = 0;
2345
2346 if (who != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002347 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002348 return admin != null ? admin.minimumPasswordLetters : length;
2349 }
2350
Jessica Hummel91da58d2014-04-10 17:39:43 +01002351 // Return strictest policy for this user and profiles that are visible from this user.
2352 List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
2353 for (UserInfo userInfo : profiles) {
Benjamin Franzfadb2b32015-01-14 18:22:42 +00002354 DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002355 final int N = policy.mAdminList.size();
2356 for (int i=0; i<N; i++) {
2357 ActiveAdmin admin = policy.mAdminList.get(i);
2358 if (length < admin.minimumPasswordLetters) {
2359 length = admin.minimumPasswordLetters;
2360 }
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002361 }
2362 }
2363 return length;
2364 }
2365 }
2366
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002367 public void setPasswordMinimumNumeric(ComponentName who, int length, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002368 if (!mHasFeature) {
2369 return;
2370 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002371 enforceCrossUserPermission(userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002372 synchronized (this) {
2373 if (who == null) {
2374 throw new NullPointerException("ComponentName is null");
2375 }
2376 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
2377 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
2378 if (ap.minimumPasswordNumeric != length) {
2379 ap.minimumPasswordNumeric = length;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002380 saveSettingsLocked(userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002381 }
2382 }
2383 }
2384
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002385 public int getPasswordMinimumNumeric(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002386 if (!mHasFeature) {
2387 return 0;
2388 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002389 enforceCrossUserPermission(userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002390 synchronized (this) {
2391 int length = 0;
2392
2393 if (who != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002394 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002395 return admin != null ? admin.minimumPasswordNumeric : length;
2396 }
2397
Jessica Hummel91da58d2014-04-10 17:39:43 +01002398 // Return strictest policy for this user and profiles that are visible from this user.
2399 List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
2400 for (UserInfo userInfo : profiles) {
Benjamin Franzfadb2b32015-01-14 18:22:42 +00002401 DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002402 final int N = policy.mAdminList.size();
2403 for (int i = 0; i < N; i++) {
2404 ActiveAdmin admin = policy.mAdminList.get(i);
2405 if (length < admin.minimumPasswordNumeric) {
2406 length = admin.minimumPasswordNumeric;
2407 }
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002408 }
2409 }
2410 return length;
2411 }
2412 }
2413
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002414 public void setPasswordMinimumSymbols(ComponentName who, int length, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002415 if (!mHasFeature) {
2416 return;
2417 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002418 enforceCrossUserPermission(userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002419 synchronized (this) {
2420 if (who == null) {
2421 throw new NullPointerException("ComponentName is null");
2422 }
2423 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
2424 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
2425 if (ap.minimumPasswordSymbols != length) {
2426 ap.minimumPasswordSymbols = length;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002427 saveSettingsLocked(userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002428 }
2429 }
2430 }
2431
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002432 public int getPasswordMinimumSymbols(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002433 if (!mHasFeature) {
2434 return 0;
2435 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002436 enforceCrossUserPermission(userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002437 synchronized (this) {
2438 int length = 0;
2439
2440 if (who != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002441 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002442 return admin != null ? admin.minimumPasswordSymbols : length;
2443 }
2444
Jessica Hummel91da58d2014-04-10 17:39:43 +01002445 // Return strictest policy for this user and profiles that are visible from this user.
2446 List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
2447 for (UserInfo userInfo : profiles) {
Benjamin Franzfadb2b32015-01-14 18:22:42 +00002448 DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002449 final int N = policy.mAdminList.size();
2450 for (int i=0; i<N; i++) {
2451 ActiveAdmin admin = policy.mAdminList.get(i);
2452 if (length < admin.minimumPasswordSymbols) {
2453 length = admin.minimumPasswordSymbols;
2454 }
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002455 }
2456 }
2457 return length;
2458 }
2459 }
2460
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002461 public void setPasswordMinimumNonLetter(ComponentName who, int length, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002462 if (!mHasFeature) {
2463 return;
2464 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002465 enforceCrossUserPermission(userHandle);
Konstantin Lopyrevc8577402010-06-04 17:15:02 -07002466 synchronized (this) {
2467 if (who == null) {
2468 throw new NullPointerException("ComponentName is null");
2469 }
2470 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
2471 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
2472 if (ap.minimumPasswordNonLetter != length) {
2473 ap.minimumPasswordNonLetter = length;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002474 saveSettingsLocked(userHandle);
Konstantin Lopyrevc8577402010-06-04 17:15:02 -07002475 }
2476 }
2477 }
2478
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002479 public int getPasswordMinimumNonLetter(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002480 if (!mHasFeature) {
2481 return 0;
2482 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002483 enforceCrossUserPermission(userHandle);
Konstantin Lopyrevc8577402010-06-04 17:15:02 -07002484 synchronized (this) {
2485 int length = 0;
2486
2487 if (who != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002488 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
Konstantin Lopyrevc8577402010-06-04 17:15:02 -07002489 return admin != null ? admin.minimumPasswordNonLetter : length;
2490 }
2491
Jessica Hummel91da58d2014-04-10 17:39:43 +01002492 // Return strictest policy for this user and profiles that are visible from this user.
2493 List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
2494 for (UserInfo userInfo : profiles) {
Benjamin Franzfadb2b32015-01-14 18:22:42 +00002495 DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002496 final int N = policy.mAdminList.size();
2497 for (int i=0; i<N; i++) {
2498 ActiveAdmin admin = policy.mAdminList.get(i);
2499 if (length < admin.minimumPasswordNonLetter) {
2500 length = admin.minimumPasswordNonLetter;
2501 }
Konstantin Lopyrevc8577402010-06-04 17:15:02 -07002502 }
2503 }
2504 return length;
2505 }
2506 }
2507
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002508 public boolean isActivePasswordSufficient(int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002509 if (!mHasFeature) {
2510 return true;
2511 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002512 enforceCrossUserPermission(userHandle);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002513
Dianne Hackbornd6847842010-01-12 18:14:19 -08002514 synchronized (this) {
Jessica Hummel91da58d2014-04-10 17:39:43 +01002515
2516 // The active password is stored in the user that runs the launcher
2517 // If the user this is called from is part of a profile group, that is the parent
2518 // of the group.
2519 UserInfo parent = getProfileParent(userHandle);
Benjamin Franzfadb2b32015-01-14 18:22:42 +00002520 int id = (parent == null) ? userHandle : parent.id;
2521 DevicePolicyData policy = getUserDataUnchecked(id);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002522
Dianne Hackbornd6847842010-01-12 18:14:19 -08002523 // This API can only be called by an active device admin,
2524 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002525 getActiveAdminForCallerLocked(null,
2526 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002527 if (policy.mActivePasswordQuality < getPasswordQuality(null, userHandle)
2528 || policy.mActivePasswordLength < getPasswordMinimumLength(null, userHandle)) {
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002529 return false;
2530 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002531 if (policy.mActivePasswordQuality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002532 return true;
2533 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002534 return policy.mActivePasswordUpperCase >= getPasswordMinimumUpperCase(null, userHandle)
Amith Yamasanief38a102013-12-13 09:05:26 -08002535 && policy.mActivePasswordLowerCase >= getPasswordMinimumLowerCase(null, userHandle)
2536 && policy.mActivePasswordLetters >= getPasswordMinimumLetters(null, userHandle)
2537 && policy.mActivePasswordNumeric >= getPasswordMinimumNumeric(null, userHandle)
2538 && policy.mActivePasswordSymbols >= getPasswordMinimumSymbols(null, userHandle)
2539 && policy.mActivePasswordNonLetter >= getPasswordMinimumNonLetter(null, userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08002540 }
2541 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002542
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002543 public int getCurrentFailedPasswordAttempts(int userHandle) {
Dianne Hackbornd6847842010-01-12 18:14:19 -08002544 synchronized (this) {
2545 // This API can only be called by an active device admin,
2546 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002547 getActiveAdminForCallerLocked(null,
2548 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002549
2550 // The active password is stored in the parent.
Benjamin Franzfadb2b32015-01-14 18:22:42 +00002551 UserInfo parent = getProfileParent(userHandle);
2552 int id = (parent == null) ? userHandle : parent.id;
2553 DevicePolicyData policy = getUserDataUnchecked(id);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002554
2555 return policy.mFailedPasswordAttempts;
Dianne Hackbornd6847842010-01-12 18:14:19 -08002556 }
2557 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002558
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002559 public void setMaximumFailedPasswordsForWipe(ComponentName who, int num, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002560 if (!mHasFeature) {
2561 return;
2562 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002563 enforceCrossUserPermission(userHandle);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08002564 synchronized (this) {
Jessica Hummel91da58d2014-04-10 17:39:43 +01002565 if (who == null) {
2566 throw new NullPointerException("ComponentName is null");
2567 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08002568 // This API can only be called by an active device admin,
2569 // so try to retrieve it to check that the caller is one.
2570 getActiveAdminForCallerLocked(who,
2571 DeviceAdminInfo.USES_POLICY_WIPE_DATA);
2572 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
2573 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN);
2574 if (ap.maximumFailedPasswordsForWipe != num) {
2575 ap.maximumFailedPasswordsForWipe = num;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002576 saveSettingsLocked(userHandle);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08002577 }
2578 }
2579 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002580
Amith Yamasani3a3d2122014-10-29 11:41:31 -07002581 @Override
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002582 public int getMaximumFailedPasswordsForWipe(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002583 if (!mHasFeature) {
2584 return 0;
2585 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002586 enforceCrossUserPermission(userHandle);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08002587 synchronized (this) {
Esteban Talaverafe0f24c2014-08-06 16:20:56 +01002588 ActiveAdmin admin = (who != null) ? getActiveAdminUncheckedLocked(who, userHandle)
2589 : getAdminWithMinimumFailedPasswordsForWipeLocked(userHandle);
2590 return admin != null ? admin.maximumFailedPasswordsForWipe : 0;
2591 }
2592 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002593
Amith Yamasani3a3d2122014-10-29 11:41:31 -07002594 @Override
2595 public int getProfileWithMinimumFailedPasswordsForWipe(int userHandle) {
2596 if (!mHasFeature) {
2597 return UserHandle.USER_NULL;
2598 }
2599 enforceCrossUserPermission(userHandle);
2600 synchronized (this) {
2601 ActiveAdmin admin = getAdminWithMinimumFailedPasswordsForWipeLocked(userHandle);
2602 return admin != null ? admin.getUserHandle().getIdentifier() : UserHandle.USER_NULL;
2603 }
2604 }
2605
Esteban Talaverafe0f24c2014-08-06 16:20:56 +01002606 /**
2607 * Returns the admin with the strictest policy on maximum failed passwords for this user and all
2608 * profiles that are visible from this user. If the policy for the primary and any other profile
2609 * are equal, it returns the admin for the primary profile.
2610 * Returns {@code null} if none of them have that policy set.
2611 */
2612 private ActiveAdmin getAdminWithMinimumFailedPasswordsForWipeLocked(int userHandle) {
2613 int count = 0;
2614 ActiveAdmin strictestAdmin = null;
2615 for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
Benjamin Franzfadb2b32015-01-14 18:22:42 +00002616 DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
Esteban Talaverafe0f24c2014-08-06 16:20:56 +01002617 for (ActiveAdmin admin : policy.mAdminList) {
2618 if (admin.maximumFailedPasswordsForWipe ==
2619 ActiveAdmin.DEF_MAXIMUM_FAILED_PASSWORDS_FOR_WIPE) {
2620 continue; // No max number of failed passwords policy set for this profile.
2621 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002622
Esteban Talaverafe0f24c2014-08-06 16:20:56 +01002623 // We always favor the primary profile if several profiles have the same value set.
2624 if (count == 0 ||
2625 count > admin.maximumFailedPasswordsForWipe ||
2626 (userInfo.isPrimary() && count >= admin.maximumFailedPasswordsForWipe)) {
2627 count = admin.maximumFailedPasswordsForWipe;
2628 strictestAdmin = admin;
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08002629 }
2630 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08002631 }
Esteban Talaverafe0f24c2014-08-06 16:20:56 +01002632 return strictestAdmin;
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08002633 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002634
Adrian Roosf8f56bc2014-11-20 23:55:34 +01002635 public boolean resetPassword(String passwordOrNull, int flags, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002636 if (!mHasFeature) {
2637 return false;
2638 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002639 enforceCrossUserPermission(userHandle);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002640 enforceNotManagedProfile(userHandle, "reset the password");
2641
Adrian Roosf8f56bc2014-11-20 23:55:34 +01002642 String password = passwordOrNull != null ? passwordOrNull : "";
2643
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08002644 int quality;
Dianne Hackborndf83afa2010-01-20 13:37:26 -08002645 synchronized (this) {
Jessica Hummel91da58d2014-04-10 17:39:43 +01002646 // This api can only be called by an active device admin,
Dianne Hackborndf83afa2010-01-20 13:37:26 -08002647 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002648 getActiveAdminForCallerLocked(null,
2649 DeviceAdminInfo.USES_POLICY_RESET_PASSWORD);
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002650 quality = getPasswordQuality(null, userHandle);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08002651 if (quality != DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07002652 int realQuality = LockPatternUtils.computePasswordQuality(password);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002653 if (realQuality < quality
2654 && quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
Amith Yamasanief38a102013-12-13 09:05:26 -08002655 Slog.w(LOG_TAG, "resetPassword: password quality 0x"
joonyoung.choad83c192013-04-18 13:51:08 +09002656 + Integer.toHexString(realQuality)
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07002657 + " does not meet required quality 0x"
2658 + Integer.toHexString(quality));
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08002659 return false;
2660 }
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002661 quality = Math.max(realQuality, quality);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08002662 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002663 int length = getPasswordMinimumLength(null, userHandle);
Dianne Hackborn9327f4f2010-01-29 10:38:29 -08002664 if (password.length() < length) {
Amith Yamasanief38a102013-12-13 09:05:26 -08002665 Slog.w(LOG_TAG, "resetPassword: password length " + password.length()
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07002666 + " does not meet required length " + length);
Dianne Hackborndf83afa2010-01-20 13:37:26 -08002667 return false;
2668 }
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002669 if (quality == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
2670 int letters = 0;
2671 int uppercase = 0;
2672 int lowercase = 0;
2673 int numbers = 0;
2674 int symbols = 0;
Konstantin Lopyrevc8577402010-06-04 17:15:02 -07002675 int nonletter = 0;
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002676 for (int i = 0; i < password.length(); i++) {
2677 char c = password.charAt(i);
2678 if (c >= 'A' && c <= 'Z') {
2679 letters++;
2680 uppercase++;
2681 } else if (c >= 'a' && c <= 'z') {
2682 letters++;
2683 lowercase++;
2684 } else if (c >= '0' && c <= '9') {
2685 numbers++;
Konstantin Lopyrevc8577402010-06-04 17:15:02 -07002686 nonletter++;
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002687 } else {
2688 symbols++;
Konstantin Lopyrevc8577402010-06-04 17:15:02 -07002689 nonletter++;
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002690 }
2691 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002692 int neededLetters = getPasswordMinimumLetters(null, userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002693 if(letters < neededLetters) {
Amith Yamasanief38a102013-12-13 09:05:26 -08002694 Slog.w(LOG_TAG, "resetPassword: number of letters " + letters
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002695 + " does not meet required number of letters " + neededLetters);
2696 return false;
2697 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002698 int neededNumbers = getPasswordMinimumNumeric(null, userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002699 if (numbers < neededNumbers) {
Amith Yamasanief38a102013-12-13 09:05:26 -08002700 Slog.w(LOG_TAG, "resetPassword: number of numerical digits " + numbers
Dianne Hackborn40e9f292012-11-27 19:12:23 -08002701 + " does not meet required number of numerical digits "
2702 + neededNumbers);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002703 return false;
2704 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002705 int neededLowerCase = getPasswordMinimumLowerCase(null, userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002706 if (lowercase < neededLowerCase) {
Amith Yamasanief38a102013-12-13 09:05:26 -08002707 Slog.w(LOG_TAG, "resetPassword: number of lowercase letters " + lowercase
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002708 + " does not meet required number of lowercase letters "
2709 + neededLowerCase);
2710 return false;
2711 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002712 int neededUpperCase = getPasswordMinimumUpperCase(null, userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002713 if (uppercase < neededUpperCase) {
Amith Yamasanief38a102013-12-13 09:05:26 -08002714 Slog.w(LOG_TAG, "resetPassword: number of uppercase letters " + uppercase
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002715 + " does not meet required number of uppercase letters "
2716 + neededUpperCase);
2717 return false;
2718 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002719 int neededSymbols = getPasswordMinimumSymbols(null, userHandle);
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002720 if (symbols < neededSymbols) {
Amith Yamasanief38a102013-12-13 09:05:26 -08002721 Slog.w(LOG_TAG, "resetPassword: number of special symbols " + symbols
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002722 + " does not meet required number of special symbols " + neededSymbols);
2723 return false;
2724 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002725 int neededNonLetter = getPasswordMinimumNonLetter(null, userHandle);
Konstantin Lopyrevc8577402010-06-04 17:15:02 -07002726 if (nonletter < neededNonLetter) {
Amith Yamasanief38a102013-12-13 09:05:26 -08002727 Slog.w(LOG_TAG, "resetPassword: number of non-letter characters " + nonletter
Konstantin Lopyrevc8577402010-06-04 17:15:02 -07002728 + " does not meet required number of non-letter characters "
2729 + neededNonLetter);
2730 return false;
2731 }
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07002732 }
Dianne Hackborndf83afa2010-01-20 13:37:26 -08002733 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002734
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08002735 int callingUid = Binder.getCallingUid();
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002736 DevicePolicyData policy = getUserData(userHandle);
2737 if (policy.mPasswordOwner >= 0 && policy.mPasswordOwner != callingUid) {
Amith Yamasanief38a102013-12-13 09:05:26 -08002738 Slog.w(LOG_TAG, "resetPassword: already set by another uid and not entered by user");
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08002739 return false;
2740 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002741
Dianne Hackborndf83afa2010-01-20 13:37:26 -08002742 // Don't do this with the lock held, because it is going to call
2743 // back in to the service.
2744 long ident = Binder.clearCallingIdentity();
2745 try {
2746 LockPatternUtils utils = new LockPatternUtils(mContext);
Adrian Roosf8f56bc2014-11-20 23:55:34 +01002747 if (!TextUtils.isEmpty(password)) {
2748 utils.saveLockPassword(password, quality, false, userHandle);
2749 } else {
2750 utils.clearLock(false, userHandle);
2751 }
Adrian Roosef1de652014-06-25 23:29:55 +02002752 boolean requireEntry = (flags & DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0;
2753 if (requireEntry) {
2754 utils.requireCredentialEntry(UserHandle.USER_ALL);
2755 }
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07002756 synchronized (this) {
Adrian Roosef1de652014-06-25 23:29:55 +02002757 int newOwner = requireEntry ? callingUid : -1;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002758 if (policy.mPasswordOwner != newOwner) {
2759 policy.mPasswordOwner = newOwner;
2760 saveSettingsLocked(userHandle);
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07002761 }
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08002762 }
Dianne Hackborndf83afa2010-01-20 13:37:26 -08002763 } finally {
2764 Binder.restoreCallingIdentity(ident);
2765 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002766
Dianne Hackborndf83afa2010-01-20 13:37:26 -08002767 return true;
2768 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002769
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002770 public void setMaximumTimeToLock(ComponentName who, long timeMs, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002771 if (!mHasFeature) {
2772 return;
2773 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002774 enforceCrossUserPermission(userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08002775 synchronized (this) {
2776 if (who == null) {
2777 throw new NullPointerException("ComponentName is null");
2778 }
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002779 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
Dianne Hackborn315ada72010-02-11 12:14:08 -08002780 DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
Dianne Hackbornd6847842010-01-12 18:14:19 -08002781 if (ap.maximumTimeToUnlock != timeMs) {
2782 ap.maximumTimeToUnlock = timeMs;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002783 saveSettingsLocked(userHandle);
2784 updateMaximumTimeToLockLocked(getUserData(userHandle));
Dianne Hackbornd6847842010-01-12 18:14:19 -08002785 }
2786 }
2787 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002788
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002789 void updateMaximumTimeToLockLocked(DevicePolicyData policy) {
2790 long timeMs = getMaximumTimeToLock(null, policy.mUserHandle);
2791 if (policy.mLastMaximumTimeToLock == timeMs) {
Dianne Hackborn2fe8fb22012-06-15 17:05:25 -07002792 return;
2793 }
2794
2795 long ident = Binder.clearCallingIdentity();
2796 try {
2797 if (timeMs <= 0) {
2798 timeMs = Integer.MAX_VALUE;
2799 } else {
2800 // Make sure KEEP_SCREEN_ON is disabled, since that
2801 // would allow bypassing of the maximum time to lock.
Christopher Tate62df6eb2012-09-07 15:00:54 -07002802 Settings.Global.putInt(mContext.getContentResolver(),
2803 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0);
Dianne Hackborn2fe8fb22012-06-15 17:05:25 -07002804 }
2805
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002806 policy.mLastMaximumTimeToLock = timeMs;
Jeff Brown5ce1cb22014-11-06 19:05:33 -08002807 mPowerManagerInternal.setMaximumScreenOffTimeoutFromDeviceAdmin((int)timeMs);
Dianne Hackborn2fe8fb22012-06-15 17:05:25 -07002808 } finally {
2809 Binder.restoreCallingIdentity(ident);
2810 }
2811 }
2812
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002813 public long getMaximumTimeToLock(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002814 if (!mHasFeature) {
2815 return 0;
2816 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002817 enforceCrossUserPermission(userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08002818 synchronized (this) {
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08002819 long time = 0;
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002820
Dianne Hackborn254cb442010-01-27 19:23:59 -08002821 if (who != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002822 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
Dianne Hackborn254cb442010-01-27 19:23:59 -08002823 return admin != null ? admin.maximumTimeToUnlock : time;
2824 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002825
Jessica Hummel91da58d2014-04-10 17:39:43 +01002826 // Return strictest policy for this user and profiles that are visible from this user.
2827 List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
2828 for (UserInfo userInfo : profiles) {
Benjamin Franzfadb2b32015-01-14 18:22:42 +00002829 DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
Jessica Hummel91da58d2014-04-10 17:39:43 +01002830 final int N = policy.mAdminList.size();
2831 for (int i=0; i<N; i++) {
2832 ActiveAdmin admin = policy.mAdminList.get(i);
2833 if (time == 0) {
2834 time = admin.maximumTimeToUnlock;
2835 } else if (admin.maximumTimeToUnlock != 0
2836 && time > admin.maximumTimeToUnlock) {
2837 time = admin.maximumTimeToUnlock;
2838 }
Dianne Hackbornd47c6ed2010-01-27 16:21:20 -08002839 }
2840 }
2841 return time;
Dianne Hackbornd6847842010-01-12 18:14:19 -08002842 }
2843 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002844
Dianne Hackborndf83afa2010-01-20 13:37:26 -08002845 public void lockNow() {
Amith Yamasani44a01b72013-09-16 10:44:57 -07002846 if (!mHasFeature) {
2847 return;
2848 }
Dianne Hackborndf83afa2010-01-20 13:37:26 -08002849 synchronized (this) {
2850 // This API can only be called by an active device admin,
2851 // so try to retrieve it to check that the caller is one.
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08002852 getActiveAdminForCallerLocked(null,
2853 DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002854 lockNowUnchecked();
2855 }
2856 }
2857
2858 private void lockNowUnchecked() {
2859 long ident = Binder.clearCallingIdentity();
2860 try {
2861 // Power off the display
Jeff Brown5ce1cb22014-11-06 19:05:33 -08002862 mPowerManager.goToSleep(SystemClock.uptimeMillis(),
Jeff Brown6d8fd272014-05-20 21:24:38 -07002863 PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN, 0);
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002864 // Ensure the device is locked
Adrian Roosef1de652014-06-25 23:29:55 +02002865 new LockPatternUtils(mContext).requireCredentialEntry(UserHandle.USER_ALL);
Adam Cohenf7522022012-10-03 20:03:18 -07002866 getWindowManager().lockNow(null);
Amith Yamasani599dd7c2012-09-14 23:20:08 -07002867 } catch (RemoteException e) {
2868 } finally {
2869 Binder.restoreCallingIdentity(ident);
Dianne Hackborndf83afa2010-01-20 13:37:26 -08002870 }
2871 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07002872
Ben Komaloed48c8b2011-10-17 17:30:21 -07002873 private boolean isExtStorageEncrypted() {
2874 String state = SystemProperties.get("vold.decrypt");
2875 return !"".equals(state);
2876 }
2877
Esteban Talavera808f6ef2014-08-28 17:15:54 +01002878 @Override
2879 public void enforceCanManageCaCerts(ComponentName who) {
Robin Lee306fe082014-06-19 14:04:24 +00002880 if (who == null) {
2881 mContext.enforceCallingOrSelfPermission(MANAGE_CA_CERTIFICATES, null);
2882 } else {
2883 synchronized (this) {
2884 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
2885 }
2886 }
Esteban Talavera808f6ef2014-08-28 17:15:54 +01002887 }
2888
2889 @Override
2890 public boolean installCaCert(ComponentName admin, byte[] certBuffer) throws RemoteException {
2891 enforceCanManageCaCerts(admin);
Robin Lee306fe082014-06-19 14:04:24 +00002892
Maggie Benthallda51e682013-08-08 22:35:44 -04002893 byte[] pemCert;
2894 try {
2895 X509Certificate cert = parseCert(certBuffer);
Robin Lee306fe082014-06-19 14:04:24 +00002896 pemCert = Credentials.convertToPem(cert);
Maggie Benthallda51e682013-08-08 22:35:44 -04002897 } catch (CertificateException ce) {
Amith Yamasanief38a102013-12-13 09:05:26 -08002898 Log.e(LOG_TAG, "Problem converting cert", ce);
Maggie Benthallda51e682013-08-08 22:35:44 -04002899 return false;
2900 } catch (IOException ioe) {
Amith Yamasanief38a102013-12-13 09:05:26 -08002901 Log.e(LOG_TAG, "Problem reading cert", ioe);
Maggie Benthallda51e682013-08-08 22:35:44 -04002902 return false;
2903 }
Robin Lee306fe082014-06-19 14:04:24 +00002904
2905 final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
2906 final long id = Binder.clearCallingIdentity();
Maggie Benthallda51e682013-08-08 22:35:44 -04002907 try {
Robin Lee306fe082014-06-19 14:04:24 +00002908 final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle);
Maggie Benthallda51e682013-08-08 22:35:44 -04002909 try {
2910 keyChainConnection.getService().installCaCertificate(pemCert);
2911 return true;
Robin Lee306fe082014-06-19 14:04:24 +00002912 } catch (RemoteException e) {
2913 Log.e(LOG_TAG, "installCaCertsToKeyChain(): ", e);
Maggie Benthallda51e682013-08-08 22:35:44 -04002914 } finally {
Robin Lee306fe082014-06-19 14:04:24 +00002915 keyChainConnection.close();
Maggie Benthallda51e682013-08-08 22:35:44 -04002916 }
2917 } catch (InterruptedException e1) {
Amith Yamasanief38a102013-12-13 09:05:26 -08002918 Log.w(LOG_TAG, "installCaCertsToKeyChain(): ", e1);
Maggie Benthallda51e682013-08-08 22:35:44 -04002919 Thread.currentThread().interrupt();
Robin Lee306fe082014-06-19 14:04:24 +00002920 } finally {
2921 Binder.restoreCallingIdentity(id);
Maggie Benthallda51e682013-08-08 22:35:44 -04002922 }
2923 return false;
2924 }
2925
Esteban Talavera808f6ef2014-08-28 17:15:54 +01002926 private static X509Certificate parseCert(byte[] certBuffer) throws CertificateException {
Maggie Benthallda51e682013-08-08 22:35:44 -04002927 CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
2928 return (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(
2929 certBuffer));
2930 }
2931
Esteban Talavera808f6ef2014-08-28 17:15:54 +01002932 @Override
2933 public void uninstallCaCert(ComponentName admin, String alias) {
2934 enforceCanManageCaCerts(admin);
Robin Lee306fe082014-06-19 14:04:24 +00002935
2936 final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
2937 final long id = Binder.clearCallingIdentity();
Maggie Benthallda51e682013-08-08 22:35:44 -04002938 try {
Robin Lee306fe082014-06-19 14:04:24 +00002939 final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle);
Maggie Benthallda51e682013-08-08 22:35:44 -04002940 try {
Robin Lee306fe082014-06-19 14:04:24 +00002941 keyChainConnection.getService().deleteCaCertificate(alias);
Maggie Benthallda51e682013-08-08 22:35:44 -04002942 } catch (RemoteException e) {
Amith Yamasanief38a102013-12-13 09:05:26 -08002943 Log.e(LOG_TAG, "from CaCertUninstaller: ", e);
Maggie Benthallda51e682013-08-08 22:35:44 -04002944 } finally {
2945 keyChainConnection.close();
Maggie Benthallda51e682013-08-08 22:35:44 -04002946 }
2947 } catch (InterruptedException ie) {
Amith Yamasanief38a102013-12-13 09:05:26 -08002948 Log.w(LOG_TAG, "CaCertUninstaller: ", ie);
Maggie Benthallda51e682013-08-08 22:35:44 -04002949 Thread.currentThread().interrupt();
Robin Lee306fe082014-06-19 14:04:24 +00002950 } finally {
2951 Binder.restoreCallingIdentity(id);
Maggie Benthallda51e682013-08-08 22:35:44 -04002952 }
2953 }
2954
Bernhard Bauer26408cc2014-09-08 14:07:31 +01002955 @Override
2956 public boolean installKeyPair(ComponentName who, byte[] privKey, byte[] cert, String alias) {
2957 if (who == null) {
2958 throw new NullPointerException("ComponentName is null");
2959 }
2960 synchronized (this) {
2961 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
2962 }
2963 final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
2964 final long id = Binder.clearCallingIdentity();
2965 try {
2966 final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle);
2967 try {
2968 IKeyChainService keyChain = keyChainConnection.getService();
2969 return keyChain.installKeyPair(privKey, cert, alias);
2970 } catch (RemoteException e) {
2971 Log.e(LOG_TAG, "Installing certificate", e);
2972 } finally {
2973 keyChainConnection.close();
2974 }
2975 } catch (InterruptedException e) {
2976 Log.w(LOG_TAG, "Interrupted while installing certificate", e);
2977 Thread.currentThread().interrupt();
2978 } finally {
2979 Binder.restoreCallingIdentity(id);
2980 }
2981 return false;
2982 }
2983
Suprabh Shukla89004682017-01-30 20:52:04 -08002984 private void wipeDataNoLock(boolean wipeExtRequested, String reason) {
Ben Komaloed48c8b2011-10-17 17:30:21 -07002985 // If the SD card is encrypted and non-removable, we have to force a wipe.
2986 boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted();
Ben Komaloed48c8b2011-10-17 17:30:21 -07002987
2988 // Note: we can only do the wipe via ExternalStorageFormatter if the volume is not emulated.
2989 if ((forceExtWipe || wipeExtRequested) && !Environment.isExternalStorageEmulated()) {
Dianne Hackborn42499172010-10-15 18:45:07 -07002990 Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
Masanori Oginof535cb02012-02-15 19:25:50 +09002991 intent.putExtra(ExternalStorageFormatter.EXTRA_ALWAYS_RESET, true);
Jeff Sharkey004a4b22014-09-24 11:45:24 -07002992 intent.putExtra(Intent.EXTRA_REASON, reason);
Dianne Hackborn42499172010-10-15 18:45:07 -07002993 intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
2994 mWakeLock.acquire(10000);
2995 mContext.startService(intent);
2996 } else {
2997 try {
Jeff Sharkey004a4b22014-09-24 11:45:24 -07002998 RecoverySystem.rebootWipeUserData(mContext, reason);
Paul Crowleya7e87ac2014-11-18 13:50:19 +00002999 } catch (IOException | SecurityException e) {
Julia Reynoldsfe053802014-06-30 11:41:32 -04003000 Slog.w(LOG_TAG, "Failed requesting data wipe", e);
Dianne Hackborn42499172010-10-15 18:45:07 -07003001 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08003002 }
3003 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07003004
Jeff Sharkey004a4b22014-09-24 11:45:24 -07003005 @Override
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003006 public void wipeData(int flags, final int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003007 if (!mHasFeature) {
3008 return;
3009 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003010 enforceCrossUserPermission(userHandle);
Suprabh Shukla89004682017-01-30 20:52:04 -08003011 final String source;
Dianne Hackbornd6847842010-01-12 18:14:19 -08003012 synchronized (this) {
3013 // This API can only be called by an active device admin,
3014 // so try to retrieve it to check that the caller is one.
Jeff Sharkey004a4b22014-09-24 11:45:24 -07003015 final ActiveAdmin admin = getActiveAdminForCallerLocked(null,
Dianne Hackborn8aa2e892010-01-22 11:31:30 -08003016 DeviceAdminInfo.USES_POLICY_WIPE_DATA);
Jeff Sharkey004a4b22014-09-24 11:45:24 -07003017
Paul Crowleya7e87ac2014-11-18 13:50:19 +00003018 final ComponentName cname = admin.info.getComponent();
3019 if (cname != null) {
3020 source = cname.flattenToShortString();
Jeff Sharkey004a4b22014-09-24 11:45:24 -07003021 } else {
Paul Crowleya7e87ac2014-11-18 13:50:19 +00003022 source = admin.info.getPackageName();
Jeff Sharkey004a4b22014-09-24 11:45:24 -07003023 }
3024
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08003025 long ident = Binder.clearCallingIdentity();
3026 try {
Paul Crowleya7e87ac2014-11-18 13:50:19 +00003027 if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) {
3028 if (userHandle != UserHandle.USER_OWNER
3029 || !isDeviceOwner(admin.info.getPackageName())) {
3030 throw new SecurityException(
3031 "Only device owner admins can set WIPE_RESET_PROTECTION_DATA");
3032 }
3033 PersistentDataBlockManager manager = (PersistentDataBlockManager)
3034 mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
Paul Crowley4c939fd2015-03-25 11:43:42 +00003035 if (manager != null) {
3036 manager.wipe();
3037 }
Paul Crowleya7e87ac2014-11-18 13:50:19 +00003038 }
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08003039 } finally {
3040 Binder.restoreCallingIdentity(ident);
3041 }
Dianne Hackborndf83afa2010-01-20 13:37:26 -08003042 }
Suprabh Shukla89004682017-01-30 20:52:04 -08003043 boolean wipeExtRequested = (flags & WIPE_EXTERNAL_STORAGE) != 0;
3044 wipeDeviceNoLock(wipeExtRequested, userHandle,
3045 "DevicePolicyManager.wipeData() from " + source);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08003046 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07003047
Suprabh Shukla89004682017-01-30 20:52:04 -08003048 private void wipeDeviceNoLock(boolean wipeExtRequested, final int userHandle, String reason) {
3049 final long iden = Binder.clearCallingIdentity();
3050 try {
3051 if (userHandle == UserHandle.USER_OWNER) {
3052 wipeDataNoLock(wipeExtRequested, reason);
3053 } else {
3054 mHandler.post(new Runnable() {
3055 public void run() {
3056 try {
3057 IActivityManager am = ActivityManagerNative.getDefault();
3058 if (am.getCurrentUser().id == userHandle) {
3059 am.switchUser(UserHandle.USER_OWNER);
3060 }
3061 if (!mUserManager.removeUser(userHandle)) {
3062 Slog.w(LOG_TAG, "Couldn't remove user " + userHandle);
3063 }
3064 } catch (RemoteException re) {
3065 // Shouldn't happen
Kenny Guye9acb592015-02-04 17:55:42 +00003066 }
Amith Yamasani32f07422012-11-16 15:09:13 -08003067 }
Suprabh Shukla89004682017-01-30 20:52:04 -08003068 });
3069 }
3070 } finally {
3071 Binder.restoreCallingIdentity(iden);
Amith Yamasani32f07422012-11-16 15:09:13 -08003072 }
3073 }
3074
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003075 public void getRemoveWarning(ComponentName comp, final RemoteCallback result, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003076 if (!mHasFeature) {
3077 return;
3078 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003079 enforceCrossUserPermission(userHandle);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08003080 mContext.enforceCallingOrSelfPermission(
3081 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
Konstantin Lopyrev32558232010-05-20 16:18:05 -07003082
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08003083 synchronized (this) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003084 ActiveAdmin admin = getActiveAdminUncheckedLocked(comp, userHandle);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08003085 if (admin == null) {
3086 try {
3087 result.sendResult(null);
3088 } catch (RemoteException e) {
3089 }
3090 return;
3091 }
Dianne Hackbornef6b22f2010-02-16 20:38:49 -08003092 Intent intent = new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_DISABLE_REQUESTED);
Dianne Hackborn8ddeee92014-07-22 16:12:59 -07003093 intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08003094 intent.setComponent(admin.info.getComponent());
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003095 mContext.sendOrderedBroadcastAsUser(intent, new UserHandle(userHandle),
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07003096 null, new BroadcastReceiver() {
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08003097 @Override
3098 public void onReceive(Context context, Intent intent) {
3099 try {
3100 result.sendResult(getResultExtras(false));
3101 } catch (RemoteException e) {
3102 }
3103 }
3104 }, null, Activity.RESULT_OK, null, null);
Dianne Hackbornd6847842010-01-12 18:14:19 -08003105 }
3106 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07003107
Konstantin Lopyreva15dcfa2010-05-24 17:10:56 -07003108 public void setActivePasswordState(int quality, int length, int letters, int uppercase,
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003109 int lowercase, int numbers, int symbols, int nonletter, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003110 if (!mHasFeature) {
3111 return;
3112 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003113 enforceCrossUserPermission(userHandle);
Jessica Hummel91da58d2014-04-10 17:39:43 +01003114 enforceNotManagedProfile(userHandle, "set the active password");
3115
Dianne Hackbornd6847842010-01-12 18:14:19 -08003116 mContext.enforceCallingOrSelfPermission(
3117 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003118 DevicePolicyData p = getUserData(userHandle);
Konstantin Lopyrev32558232010-05-20 16:18:05 -07003119
Dianne Hackborn85f2c9c2010-03-22 11:12:48 -07003120 validateQualityConstant(quality);
Konstantin Lopyrev32558232010-05-20 16:18:05 -07003121
Dianne Hackbornd6847842010-01-12 18:14:19 -08003122 synchronized (this) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003123 if (p.mActivePasswordQuality != quality || p.mActivePasswordLength != length
3124 || p.mFailedPasswordAttempts != 0 || p.mActivePasswordLetters != letters
3125 || p.mActivePasswordUpperCase != uppercase
Amith Yamasanief38a102013-12-13 09:05:26 -08003126 || p.mActivePasswordLowerCase != lowercase
3127 || p.mActivePasswordNumeric != numbers
3128 || p.mActivePasswordSymbols != symbols
3129 || p.mActivePasswordNonLetter != nonletter) {
Dianne Hackbornd6847842010-01-12 18:14:19 -08003130 long ident = Binder.clearCallingIdentity();
3131 try {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003132 p.mActivePasswordQuality = quality;
3133 p.mActivePasswordLength = length;
3134 p.mActivePasswordLetters = letters;
3135 p.mActivePasswordLowerCase = lowercase;
3136 p.mActivePasswordUpperCase = uppercase;
3137 p.mActivePasswordNumeric = numbers;
3138 p.mActivePasswordSymbols = symbols;
3139 p.mActivePasswordNonLetter = nonletter;
3140 p.mFailedPasswordAttempts = 0;
3141 saveSettingsLocked(userHandle);
3142 updatePasswordExpirationsLocked(userHandle);
3143 setExpirationAlarmCheckLocked(mContext, p);
Jessica Hummel91da58d2014-04-10 17:39:43 +01003144 sendAdminCommandToSelfAndProfilesLocked(
3145 DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003146 DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08003147 } finally {
3148 Binder.restoreCallingIdentity(ident);
3149 }
3150 }
3151 }
3152 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07003153
Andy Stadler043116a2010-11-29 17:43:32 -08003154 /**
Jessica Hummel91da58d2014-04-10 17:39:43 +01003155 * Called any time the device password is updated. Resets all password expiration clocks.
Andy Stadler043116a2010-11-29 17:43:32 -08003156 */
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003157 private void updatePasswordExpirationsLocked(int userHandle) {
Jessica Hummel91da58d2014-04-10 17:39:43 +01003158 List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
3159 for (UserInfo userInfo : profiles) {
Jim Millere303bf42014-08-26 17:12:29 -07003160 int profileId = userInfo.id;
Benjamin Franzfadb2b32015-01-14 18:22:42 +00003161 DevicePolicyData policy = getUserDataUnchecked(profileId);
Jessica Hummel91da58d2014-04-10 17:39:43 +01003162 final int N = policy.mAdminList.size();
3163 if (N > 0) {
3164 for (int i=0; i<N; i++) {
3165 ActiveAdmin admin = policy.mAdminList.get(i);
3166 if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) {
3167 long timeout = admin.passwordExpirationTimeout;
3168 long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L;
3169 admin.passwordExpirationDate = expiration;
3170 }
3171 }
Jim Millera4e28d12010-11-08 16:15:47 -08003172 }
Jessica Hummel91da58d2014-04-10 17:39:43 +01003173 saveSettingsLocked(profileId);
Jim Millera4e28d12010-11-08 16:15:47 -08003174 }
Jim Millera4e28d12010-11-08 16:15:47 -08003175 }
3176
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003177 public void reportFailedPasswordAttempt(int userHandle) {
3178 enforceCrossUserPermission(userHandle);
Jessica Hummel91da58d2014-04-10 17:39:43 +01003179 enforceNotManagedProfile(userHandle, "report failed password attempt");
Dianne Hackbornd6847842010-01-12 18:14:19 -08003180 mContext.enforceCallingOrSelfPermission(
3181 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
Konstantin Lopyrev32558232010-05-20 16:18:05 -07003182
Craig Mautner66eb5212014-09-04 12:56:39 -07003183 long ident = Binder.clearCallingIdentity();
3184 try {
3185 boolean wipeData = false;
3186 int identifier = 0;
3187 synchronized (this) {
3188 DevicePolicyData policy = getUserData(userHandle);
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003189 policy.mFailedPasswordAttempts++;
3190 saveSettingsLocked(userHandle);
Amith Yamasani44a01b72013-09-16 10:44:57 -07003191 if (mHasFeature) {
Esteban Talaverafe0f24c2014-08-06 16:20:56 +01003192 ActiveAdmin strictestAdmin =
3193 getAdminWithMinimumFailedPasswordsForWipeLocked(userHandle);
Adrian Roosb8b47742014-08-07 15:55:18 +02003194 int max = strictestAdmin != null
3195 ? strictestAdmin.maximumFailedPasswordsForWipe : 0;
Amith Yamasani44a01b72013-09-16 10:44:57 -07003196 if (max > 0 && policy.mFailedPasswordAttempts >= max) {
Esteban Talaverafe0f24c2014-08-06 16:20:56 +01003197 // Wipe the user/profile associated with the policy that was violated. This
3198 // is not necessarily calling user: if the policy that fired was from a
3199 // managed profile rather than the main user profile, we wipe former only.
Craig Mautner66eb5212014-09-04 12:56:39 -07003200 wipeData = true;
3201 identifier = strictestAdmin.getUserHandle().getIdentifier();
Amith Yamasani44a01b72013-09-16 10:44:57 -07003202 }
Jessica Hummel91da58d2014-04-10 17:39:43 +01003203 sendAdminCommandToSelfAndProfilesLocked(
3204 DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
Amith Yamasani44a01b72013-09-16 10:44:57 -07003205 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
Dianne Hackborn8ea138c2010-01-26 18:01:04 -08003206 }
Dianne Hackbornd6847842010-01-12 18:14:19 -08003207 }
Craig Mautner66eb5212014-09-04 12:56:39 -07003208 if (wipeData) {
3209 // Call without holding lock.
Suprabh Shukla89004682017-01-30 20:52:04 -08003210 wipeDeviceNoLock(false, identifier,
Paul Crowleya7e87ac2014-11-18 13:50:19 +00003211 "reportFailedPasswordAttempt()");
Craig Mautner66eb5212014-09-04 12:56:39 -07003212 }
3213 } finally {
3214 Binder.restoreCallingIdentity(ident);
Dianne Hackbornd6847842010-01-12 18:14:19 -08003215 }
3216 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07003217
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003218 public void reportSuccessfulPasswordAttempt(int userHandle) {
3219 enforceCrossUserPermission(userHandle);
Dianne Hackbornd6847842010-01-12 18:14:19 -08003220 mContext.enforceCallingOrSelfPermission(
3221 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
Konstantin Lopyrev32558232010-05-20 16:18:05 -07003222
Dianne Hackbornd6847842010-01-12 18:14:19 -08003223 synchronized (this) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003224 DevicePolicyData policy = getUserData(userHandle);
3225 if (policy.mFailedPasswordAttempts != 0 || policy.mPasswordOwner >= 0) {
Dianne Hackbornd6847842010-01-12 18:14:19 -08003226 long ident = Binder.clearCallingIdentity();
3227 try {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003228 policy.mFailedPasswordAttempts = 0;
3229 policy.mPasswordOwner = -1;
3230 saveSettingsLocked(userHandle);
Amith Yamasani44a01b72013-09-16 10:44:57 -07003231 if (mHasFeature) {
Jessica Hummel91da58d2014-04-10 17:39:43 +01003232 sendAdminCommandToSelfAndProfilesLocked(
3233 DeviceAdminReceiver.ACTION_PASSWORD_SUCCEEDED,
Amith Yamasani44a01b72013-09-16 10:44:57 -07003234 DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
3235 }
Dianne Hackbornd6847842010-01-12 18:14:19 -08003236 } finally {
3237 Binder.restoreCallingIdentity(ident);
3238 }
3239 }
3240 }
3241 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07003242
Oscar Montemayor69238c62010-08-03 10:51:06 -07003243 public ComponentName setGlobalProxy(ComponentName who, String proxySpec,
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003244 String exclusionList, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003245 if (!mHasFeature) {
3246 return null;
3247 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003248 enforceCrossUserPermission(userHandle);
Oscar Montemayor69238c62010-08-03 10:51:06 -07003249 synchronized(this) {
3250 if (who == null) {
3251 throw new NullPointerException("ComponentName is null");
3252 }
3253
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003254 // Only check if owner has set global proxy. We don't allow other users to set it.
3255 DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
Oscar Montemayor69238c62010-08-03 10:51:06 -07003256 ActiveAdmin admin = getActiveAdminForCallerLocked(who,
3257 DeviceAdminInfo.USES_POLICY_SETS_GLOBAL_PROXY);
3258
3259 // Scan through active admins and find if anyone has already
3260 // set the global proxy.
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003261 Set<ComponentName> compSet = policy.mAdminMap.keySet();
Jessica Hummel91da58d2014-04-10 17:39:43 +01003262 for (ComponentName component : compSet) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003263 ActiveAdmin ap = policy.mAdminMap.get(component);
Oscar Montemayor69238c62010-08-03 10:51:06 -07003264 if ((ap.specifiesGlobalProxy) && (!component.equals(who))) {
3265 // Another admin already sets the global proxy
3266 // Return it to the caller.
3267 return component;
3268 }
3269 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003270
3271 // If the user is not the owner, don't set the global proxy. Fail silently.
3272 if (UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
Amith Yamasanief38a102013-12-13 09:05:26 -08003273 Slog.w(LOG_TAG, "Only the owner is allowed to set the global proxy. User "
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003274 + userHandle + " is not permitted.");
3275 return null;
3276 }
Oscar Montemayor69238c62010-08-03 10:51:06 -07003277 if (proxySpec == null) {
3278 admin.specifiesGlobalProxy = false;
3279 admin.globalProxySpec = null;
3280 admin.globalProxyExclusionList = null;
3281 } else {
3282
3283 admin.specifiesGlobalProxy = true;
3284 admin.globalProxySpec = proxySpec;
3285 admin.globalProxyExclusionList = exclusionList;
3286 }
3287
3288 // Reset the global proxy accordingly
3289 // Do this using system permissions, as apps cannot write to secure settings
3290 long origId = Binder.clearCallingIdentity();
Jessica Hummel91da58d2014-04-10 17:39:43 +01003291 try {
3292 resetGlobalProxyLocked(policy);
3293 } finally {
3294 Binder.restoreCallingIdentity(origId);
3295 }
Oscar Montemayor69238c62010-08-03 10:51:06 -07003296 return null;
3297 }
3298 }
3299
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003300 public ComponentName getGlobalProxyAdmin(int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003301 if (!mHasFeature) {
3302 return null;
3303 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003304 enforceCrossUserPermission(userHandle);
Oscar Montemayor69238c62010-08-03 10:51:06 -07003305 synchronized(this) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003306 DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
Oscar Montemayor69238c62010-08-03 10:51:06 -07003307 // Scan through active admins and find if anyone has already
3308 // set the global proxy.
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003309 final int N = policy.mAdminList.size();
Oscar Montemayor69238c62010-08-03 10:51:06 -07003310 for (int i = 0; i < N; i++) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003311 ActiveAdmin ap = policy.mAdminList.get(i);
Oscar Montemayor69238c62010-08-03 10:51:06 -07003312 if (ap.specifiesGlobalProxy) {
3313 // Device admin sets the global proxy
3314 // Return it to the caller.
3315 return ap.info.getComponent();
3316 }
3317 }
3318 }
3319 // No device admin sets the global proxy.
3320 return null;
3321 }
3322
Jason Monk03bc9912014-05-13 09:44:57 -04003323 public void setRecommendedGlobalProxy(ComponentName who, ProxyInfo proxyInfo) {
3324 synchronized (this) {
3325 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
3326 }
3327 long token = Binder.clearCallingIdentity();
3328 try {
3329 ConnectivityManager connectivityManager = (ConnectivityManager)
3330 mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
3331 connectivityManager.setGlobalProxy(proxyInfo);
3332 } finally {
3333 Binder.restoreCallingIdentity(token);
3334 }
3335 }
3336
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003337 private void resetGlobalProxyLocked(DevicePolicyData policy) {
3338 final int N = policy.mAdminList.size();
Oscar Montemayor69238c62010-08-03 10:51:06 -07003339 for (int i = 0; i < N; i++) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003340 ActiveAdmin ap = policy.mAdminList.get(i);
Oscar Montemayor69238c62010-08-03 10:51:06 -07003341 if (ap.specifiesGlobalProxy) {
Dianne Hackborn2fe8fb22012-06-15 17:05:25 -07003342 saveGlobalProxyLocked(ap.globalProxySpec, ap.globalProxyExclusionList);
Oscar Montemayor69238c62010-08-03 10:51:06 -07003343 return;
3344 }
3345 }
3346 // No device admins defining global proxies - reset global proxy settings to none
Dianne Hackborn2fe8fb22012-06-15 17:05:25 -07003347 saveGlobalProxyLocked(null, null);
Oscar Montemayor69238c62010-08-03 10:51:06 -07003348 }
3349
Dianne Hackborn2fe8fb22012-06-15 17:05:25 -07003350 private void saveGlobalProxyLocked(String proxySpec, String exclusionList) {
Oscar Montemayor69238c62010-08-03 10:51:06 -07003351 if (exclusionList == null) {
3352 exclusionList = "";
3353 }
3354 if (proxySpec == null) {
3355 proxySpec = "";
3356 }
3357 // Remove white spaces
3358 proxySpec = proxySpec.trim();
Robert Greenwalt434203a2010-10-11 16:00:27 -07003359 String data[] = proxySpec.split(":");
3360 int proxyPort = 8080;
3361 if (data.length > 1) {
3362 try {
3363 proxyPort = Integer.parseInt(data[1]);
3364 } catch (NumberFormatException e) {}
3365 }
Oscar Montemayor69238c62010-08-03 10:51:06 -07003366 exclusionList = exclusionList.trim();
3367 ContentResolver res = mContext.getContentResolver();
Raj Mamadgi92d02492013-11-11 13:52:58 -08003368
Jason Monk54a9ebb2014-05-07 15:26:22 -04003369 ProxyInfo proxyProperties = new ProxyInfo(data[0], proxyPort, exclusionList);
Raj Mamadgi92d02492013-11-11 13:52:58 -08003370 if (!proxyProperties.isValid()) {
Amith Yamasanief38a102013-12-13 09:05:26 -08003371 Slog.e(LOG_TAG, "Invalid proxy properties, ignoring: " + proxyProperties.toString());
Raj Mamadgi92d02492013-11-11 13:52:58 -08003372 return;
3373 }
Jeff Sharkey625239a2012-09-26 22:03:49 -07003374 Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_HOST, data[0]);
3375 Settings.Global.putInt(res, Settings.Global.GLOBAL_HTTP_PROXY_PORT, proxyPort);
3376 Settings.Global.putString(res, Settings.Global.GLOBAL_HTTP_PROXY_EXCLUSION_LIST,
Robert Greenwalt434203a2010-10-11 16:00:27 -07003377 exclusionList);
Oscar Montemayor69238c62010-08-03 10:51:06 -07003378 }
3379
Andy Stadler7b0f8f02011-01-12 14:59:52 -08003380 /**
Andy Stadler22dbfda2011-01-17 12:47:31 -08003381 * Set the storage encryption request for a single admin. Returns the new total request
3382 * status (for all admins).
Andy Stadler7b0f8f02011-01-12 14:59:52 -08003383 */
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003384 public int setStorageEncryption(ComponentName who, boolean encrypt, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003385 if (!mHasFeature) {
3386 return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
3387 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003388 enforceCrossUserPermission(userHandle);
Andy Stadler7b0f8f02011-01-12 14:59:52 -08003389 synchronized (this) {
3390 // Check for permissions
3391 if (who == null) {
3392 throw new NullPointerException("ComponentName is null");
3393 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003394 // Only owner can set storage encryption
3395 if (userHandle != UserHandle.USER_OWNER
3396 || UserHandle.getCallingUserId() != UserHandle.USER_OWNER) {
Amith Yamasanief38a102013-12-13 09:05:26 -08003397 Slog.w(LOG_TAG, "Only owner is allowed to set storage encryption. User "
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003398 + UserHandle.getCallingUserId() + " is not permitted.");
3399 return 0;
3400 }
3401
Andy Stadler7b0f8f02011-01-12 14:59:52 -08003402 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
3403 DeviceAdminInfo.USES_ENCRYPTED_STORAGE);
3404
Andy Stadler22dbfda2011-01-17 12:47:31 -08003405 // Quick exit: If the filesystem does not support encryption, we can exit early.
3406 if (!isEncryptionSupported()) {
3407 return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
3408 }
3409
3410 // (1) Record the value for the admin so it's sticky
3411 if (ap.encryptionRequested != encrypt) {
3412 ap.encryptionRequested = encrypt;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003413 saveSettingsLocked(userHandle);
Andy Stadler22dbfda2011-01-17 12:47:31 -08003414 }
3415
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003416 DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
Andy Stadler22dbfda2011-01-17 12:47:31 -08003417 // (2) Compute "max" for all admins
3418 boolean newRequested = false;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003419 final int N = policy.mAdminList.size();
Andy Stadler22dbfda2011-01-17 12:47:31 -08003420 for (int i = 0; i < N; i++) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003421 newRequested |= policy.mAdminList.get(i).encryptionRequested;
Andy Stadler22dbfda2011-01-17 12:47:31 -08003422 }
3423
3424 // Notify OS of new request
3425 setEncryptionRequested(newRequested);
3426
3427 // Return the new global request status
3428 return newRequested
3429 ? DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE
3430 : DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
Andy Stadler7b0f8f02011-01-12 14:59:52 -08003431 }
3432 }
3433
3434 /**
Andy Stadler22dbfda2011-01-17 12:47:31 -08003435 * Get the current storage encryption request status for a given admin, or aggregate of all
3436 * active admins.
Andy Stadler7b0f8f02011-01-12 14:59:52 -08003437 */
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003438 public boolean getStorageEncryption(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003439 if (!mHasFeature) {
3440 return false;
3441 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003442 enforceCrossUserPermission(userHandle);
Andy Stadler7b0f8f02011-01-12 14:59:52 -08003443 synchronized (this) {
3444 // Check for permissions if a particular caller is specified
3445 if (who != null) {
Andy Stadler22dbfda2011-01-17 12:47:31 -08003446 // When checking for a single caller, status is based on caller's request
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003447 ActiveAdmin ap = getActiveAdminUncheckedLocked(who, userHandle);
Andy Stadlerc994d692011-06-01 15:30:54 -07003448 return ap != null ? ap.encryptionRequested : false;
Andy Stadler7b0f8f02011-01-12 14:59:52 -08003449 }
3450
Andy Stadler22dbfda2011-01-17 12:47:31 -08003451 // If no particular caller is specified, return the aggregate set of requests.
3452 // This is short circuited by returning true on the first hit.
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003453 DevicePolicyData policy = getUserData(userHandle);
3454 final int N = policy.mAdminList.size();
Andy Stadler22dbfda2011-01-17 12:47:31 -08003455 for (int i = 0; i < N; i++) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003456 if (policy.mAdminList.get(i).encryptionRequested) {
Andy Stadler22dbfda2011-01-17 12:47:31 -08003457 return true;
3458 }
3459 }
3460 return false;
Andy Stadler7b0f8f02011-01-12 14:59:52 -08003461 }
3462 }
3463
Andy Stadler22dbfda2011-01-17 12:47:31 -08003464 /**
3465 * Get the current encryption status of the device.
3466 */
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003467 public int getStorageEncryptionStatus(int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003468 if (!mHasFeature) {
3469 // Ok to return current status.
3470 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003471 enforceCrossUserPermission(userHandle);
Andy Stadler22dbfda2011-01-17 12:47:31 -08003472 return getEncryptionStatus();
3473 }
3474
3475 /**
3476 * Hook to low-levels: This should report if the filesystem supports encrypted storage.
3477 */
3478 private boolean isEncryptionSupported() {
3479 // Note, this can be implemented as
3480 // return getEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
3481 // But is provided as a separate internal method if there's a faster way to do a
3482 // simple check for supported-or-not.
3483 return getEncryptionStatus() != DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
3484 }
3485
3486 /**
3487 * Hook to low-levels: Reporting the current status of encryption.
3488 * @return A value such as {@link DevicePolicyManager#ENCRYPTION_STATUS_UNSUPPORTED} or
3489 * {@link DevicePolicyManager#ENCRYPTION_STATUS_INACTIVE} or
3490 * {@link DevicePolicyManager#ENCRYPTION_STATUS_ACTIVE}.
3491 */
3492 private int getEncryptionStatus() {
Amir Samuelov1213e2f2014-10-14 13:15:30 +03003493 String pfeStatus = SystemProperties.get("vold.pfe", "");
3494 if ("activated".equalsIgnoreCase(pfeStatus)) {
3495 return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
3496 }
3497
Andy Stadler0fe45de2011-01-20 16:35:09 -08003498 String status = SystemProperties.get("ro.crypto.state", "unsupported");
3499 if ("encrypted".equalsIgnoreCase(status)) {
Amith Yamasanicd410ba2014-10-17 11:16:58 -07003500 final long token = Binder.clearCallingIdentity();
3501 try {
3502 return LockPatternUtils.isDeviceEncrypted()
3503 ? DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE
3504 : DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
3505 } finally {
3506 Binder.restoreCallingIdentity(token);
3507 }
Andy Stadler0fe45de2011-01-20 16:35:09 -08003508 } else if ("unencrypted".equalsIgnoreCase(status)) {
3509 return DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
3510 } else {
3511 return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
3512 }
Andy Stadler22dbfda2011-01-17 12:47:31 -08003513 }
3514
3515 /**
3516 * Hook to low-levels: If needed, record the new admin setting for encryption.
3517 */
3518 private void setEncryptionRequested(boolean encrypt) {
3519 }
3520
Sander Alewijnsed2a1eec2014-07-09 12:57:05 +01003521
3522 /**
3523 * Set whether the screen capture is disabled for the user managed by the specified admin.
3524 */
3525 public void setScreenCaptureDisabled(ComponentName who, int userHandle, boolean disabled) {
3526 if (!mHasFeature) {
3527 return;
3528 }
Sander Alewijnse0ced6272014-08-26 11:18:26 +01003529 enforceCrossUserPermission(userHandle);
Sander Alewijnsed2a1eec2014-07-09 12:57:05 +01003530 synchronized (this) {
3531 if (who == null) {
3532 throw new NullPointerException("ComponentName is null");
3533 }
3534 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
3535 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
3536 if (ap.disableScreenCapture != disabled) {
3537 ap.disableScreenCapture = disabled;
3538 saveSettingsLocked(userHandle);
Sander Alewijnsea87863a2014-07-29 12:01:38 +01003539 updateScreenCaptureDisabledInWindowManager(userHandle, disabled);
Sander Alewijnsed2a1eec2014-07-09 12:57:05 +01003540 }
3541 }
3542 }
3543
3544 /**
3545 * Returns whether or not screen capture is disabled for a given admin, or disabled for any
3546 * active admin (if given admin is null).
3547 */
3548 public boolean getScreenCaptureDisabled(ComponentName who, int userHandle) {
3549 if (!mHasFeature) {
3550 return false;
3551 }
3552 synchronized (this) {
3553 if (who != null) {
3554 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
3555 return (admin != null) ? admin.disableScreenCapture : false;
3556 }
3557
3558 DevicePolicyData policy = getUserData(userHandle);
3559 final int N = policy.mAdminList.size();
3560 for (int i = 0; i < N; i++) {
3561 ActiveAdmin admin = policy.mAdminList.get(i);
3562 if (admin.disableScreenCapture) {
3563 return true;
3564 }
3565 }
3566 return false;
3567 }
3568 }
3569
Sander Alewijnsea87863a2014-07-29 12:01:38 +01003570 private void updateScreenCaptureDisabledInWindowManager(int userHandle, boolean disabled) {
3571 long ident = Binder.clearCallingIdentity();
3572 try {
3573 getWindowManager().setScreenCaptureDisabled(userHandle, disabled);
3574 } catch (RemoteException e) {
3575 Log.w(LOG_TAG, "Unable to notify WindowManager.", e);
3576 } finally {
3577 Binder.restoreCallingIdentity(ident);
3578 }
3579 }
3580
Ben Komalo2447edd2011-05-09 16:05:33 -07003581 /**
Sander Alewijnse0ced6272014-08-26 11:18:26 +01003582 * Set whether auto time is required by the specified admin (must be device owner).
3583 */
3584 public void setAutoTimeRequired(ComponentName who, int userHandle, boolean required) {
3585 if (!mHasFeature) {
3586 return;
3587 }
3588 enforceCrossUserPermission(userHandle);
3589 synchronized (this) {
3590 if (who == null) {
3591 throw new NullPointerException("ComponentName is null");
3592 }
3593 ActiveAdmin admin = getActiveAdminForCallerLocked(who,
3594 DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
3595 if (admin.requireAutoTime != required) {
3596 admin.requireAutoTime = required;
3597 saveSettingsLocked(userHandle);
3598 }
3599 }
3600
3601 // Turn AUTO_TIME on in settings if it is required
3602 if (required) {
3603 long ident = Binder.clearCallingIdentity();
3604 try {
3605 Settings.Global.putInt(mContext.getContentResolver(),
3606 Settings.Global.AUTO_TIME, 1 /* AUTO_TIME on */);
3607 } finally {
3608 Binder.restoreCallingIdentity(ident);
3609 }
3610 }
3611 }
3612
3613 /**
3614 * Returns whether or not auto time is required by the device owner.
3615 */
3616 public boolean getAutoTimeRequired() {
3617 if (!mHasFeature) {
3618 return false;
3619 }
3620 synchronized (this) {
3621 ActiveAdmin deviceOwner = getDeviceOwnerAdmin();
3622 return (deviceOwner != null) ? deviceOwner.requireAutoTime : false;
3623 }
3624 }
3625
3626 /**
Ben Komalo2447edd2011-05-09 16:05:33 -07003627 * The system property used to share the state of the camera. The native camera service
3628 * is expected to read this property and act accordingly.
3629 */
3630 public static final String SYSTEM_PROP_DISABLE_CAMERA = "sys.secpolicy.camera.disabled";
3631
3632 /**
3633 * Disables all device cameras according to the specified admin.
3634 */
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003635 public void setCameraDisabled(ComponentName who, boolean disabled, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003636 if (!mHasFeature) {
3637 return;
3638 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003639 enforceCrossUserPermission(userHandle);
Ben Komalo2447edd2011-05-09 16:05:33 -07003640 synchronized (this) {
3641 if (who == null) {
3642 throw new NullPointerException("ComponentName is null");
3643 }
3644 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
3645 DeviceAdminInfo.USES_POLICY_DISABLE_CAMERA);
3646 if (ap.disableCamera != disabled) {
3647 ap.disableCamera = disabled;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003648 saveSettingsLocked(userHandle);
Ben Komalo2447edd2011-05-09 16:05:33 -07003649 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003650 syncDeviceCapabilitiesLocked(getUserData(userHandle));
Ben Komalo2447edd2011-05-09 16:05:33 -07003651 }
3652 }
3653
3654 /**
3655 * Gets whether or not all device cameras are disabled for a given admin, or disabled for any
3656 * active admins.
3657 */
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003658 public boolean getCameraDisabled(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003659 if (!mHasFeature) {
3660 return false;
3661 }
Ben Komalo2447edd2011-05-09 16:05:33 -07003662 synchronized (this) {
3663 if (who != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003664 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
Ben Komalo2447edd2011-05-09 16:05:33 -07003665 return (admin != null) ? admin.disableCamera : false;
3666 }
3667
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003668 DevicePolicyData policy = getUserData(userHandle);
Ben Komalo2447edd2011-05-09 16:05:33 -07003669 // Determine whether or not the device camera is disabled for any active admins.
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003670 final int N = policy.mAdminList.size();
Ben Komalo2447edd2011-05-09 16:05:33 -07003671 for (int i = 0; i < N; i++) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003672 ActiveAdmin admin = policy.mAdminList.get(i);
Ben Komalo2447edd2011-05-09 16:05:33 -07003673 if (admin.disableCamera) {
3674 return true;
3675 }
3676 }
3677 return false;
3678 }
3679 }
3680
Jim Millerb8ec4702012-08-31 17:19:10 -07003681 /**
Jim Miller48b9b0d2012-09-19 23:16:50 -07003682 * Selectively disable keyguard features.
Jim Millerb8ec4702012-08-31 17:19:10 -07003683 */
Jim Miller48b9b0d2012-09-19 23:16:50 -07003684 public void setKeyguardDisabledFeatures(ComponentName who, int which, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003685 if (!mHasFeature) {
3686 return;
3687 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003688 enforceCrossUserPermission(userHandle);
Robin Leea9ee6722014-05-20 16:26:49 +01003689 enforceNotManagedProfile(userHandle, "disable keyguard features");
Jim Millerb8ec4702012-08-31 17:19:10 -07003690 synchronized (this) {
3691 if (who == null) {
3692 throw new NullPointerException("ComponentName is null");
3693 }
3694 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
Jim Miller48b9b0d2012-09-19 23:16:50 -07003695 DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
3696 if (ap.disabledKeyguardFeatures != which) {
3697 ap.disabledKeyguardFeatures = which;
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003698 saveSettingsLocked(userHandle);
Jim Millerb8ec4702012-08-31 17:19:10 -07003699 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003700 syncDeviceCapabilitiesLocked(getUserData(userHandle));
Jim Millerb8ec4702012-08-31 17:19:10 -07003701 }
3702 }
3703
3704 /**
Jim Miller48b9b0d2012-09-19 23:16:50 -07003705 * Gets the disabled state for features in keyguard for the given admin,
Jim Millerb8ec4702012-08-31 17:19:10 -07003706 * or the aggregate of all active admins if who is null.
3707 */
Jim Miller48b9b0d2012-09-19 23:16:50 -07003708 public int getKeyguardDisabledFeatures(ComponentName who, int userHandle) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003709 if (!mHasFeature) {
3710 return 0;
3711 }
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003712 enforceCrossUserPermission(userHandle);
Jim Millerb8ec4702012-08-31 17:19:10 -07003713 synchronized (this) {
3714 if (who != null) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003715 ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle);
Jim Miller48b9b0d2012-09-19 23:16:50 -07003716 return (admin != null) ? admin.disabledKeyguardFeatures : 0;
Jim Millerb8ec4702012-08-31 17:19:10 -07003717 }
3718
Jim Miller48b9b0d2012-09-19 23:16:50 -07003719 // Determine which keyguard features are disabled for any active admins.
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003720 DevicePolicyData policy = getUserData(userHandle);
3721 final int N = policy.mAdminList.size();
Jim Millerb8ec4702012-08-31 17:19:10 -07003722 int which = 0;
3723 for (int i = 0; i < N; i++) {
Amith Yamasani599dd7c2012-09-14 23:20:08 -07003724 ActiveAdmin admin = policy.mAdminList.get(i);
Jim Miller48b9b0d2012-09-19 23:16:50 -07003725 which |= admin.disabledKeyguardFeatures;
Jim Millerb8ec4702012-08-31 17:19:10 -07003726 }
3727 return which;
3728 }
3729 }
3730
Amith Yamasani71e6c692013-03-24 17:39:28 -07003731 @Override
Geoffrey Borggaard334c7e32013-08-08 14:31:36 -04003732 public boolean setDeviceOwner(String packageName, String ownerName) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003733 if (!mHasFeature) {
3734 return false;
3735 }
Amith Yamasani71e6c692013-03-24 17:39:28 -07003736 if (packageName == null
3737 || !DeviceOwner.isInstalled(packageName, mContext.getPackageManager())) {
3738 throw new IllegalArgumentException("Invalid package name " + packageName
3739 + " for device owner");
3740 }
3741 synchronized (this) {
Esteban Talaverab5ef1622014-09-08 17:49:01 +01003742 if (!allowedToSetDeviceOwnerOnDevice()) {
Adam Connors776c5552014-01-09 10:42:56 +00003743 throw new IllegalStateException(
3744 "Trying to set device owner but device is already provisioned.");
3745 }
3746
3747 if (mDeviceOwner != null && mDeviceOwner.hasDeviceOwner()) {
3748 throw new IllegalStateException(
3749 "Trying to set device owner but device owner is already set.");
3750 }
3751
Zoltan Szatmary-Ban26ac6a62014-11-13 20:49:43 +00003752 // Shutting down backup manager service permanently.
3753 long ident = Binder.clearCallingIdentity();
3754 try {
3755 IBackupManager ibm = IBackupManager.Stub.asInterface(
3756 ServiceManager.getService(Context.BACKUP_SERVICE));
3757 ibm.setBackupServiceActive(UserHandle.USER_OWNER, false);
3758 } catch (RemoteException e) {
3759 throw new IllegalStateException("Failed deactivating backup service.", e);
3760 } finally {
3761 Binder.restoreCallingIdentity(ident);
3762 }
3763
Adam Connors776c5552014-01-09 10:42:56 +00003764 if (mDeviceOwner == null) {
3765 // Device owner is not set and does not exist, set it.
3766 mDeviceOwner = DeviceOwner.createWithDeviceOwner(packageName, ownerName);
Amith Yamasani71e6c692013-03-24 17:39:28 -07003767 mDeviceOwner.writeOwnerFile();
3768 return true;
3769 } else {
Adam Connors776c5552014-01-09 10:42:56 +00003770 // Device owner is not set but a profile owner exists, update Device owner state.
3771 mDeviceOwner.setDeviceOwner(packageName, ownerName);
3772 mDeviceOwner.writeOwnerFile();
3773 return true;
Amith Yamasani71e6c692013-03-24 17:39:28 -07003774 }
3775 }
3776 }
3777
3778 @Override
3779 public boolean isDeviceOwner(String packageName) {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003780 if (!mHasFeature) {
3781 return false;
3782 }
Amith Yamasani71e6c692013-03-24 17:39:28 -07003783 synchronized (this) {
3784 return mDeviceOwner != null
Robin Lee08fc72d2014-02-20 12:50:41 +00003785 && mDeviceOwner.hasDeviceOwner()
Adam Connors776c5552014-01-09 10:42:56 +00003786 && mDeviceOwner.getDeviceOwnerPackageName().equals(packageName);
Amith Yamasani71e6c692013-03-24 17:39:28 -07003787 }
3788 }
3789
3790 @Override
3791 public String getDeviceOwner() {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003792 if (!mHasFeature) {
3793 return null;
3794 }
Amith Yamasani71e6c692013-03-24 17:39:28 -07003795 synchronized (this) {
Alexandra Gherghinaa4fcb442014-04-24 17:55:30 +01003796 if (mDeviceOwner != null && mDeviceOwner.hasDeviceOwner()) {
Adam Connors776c5552014-01-09 10:42:56 +00003797 return mDeviceOwner.getDeviceOwnerPackageName();
Amith Yamasani71e6c692013-03-24 17:39:28 -07003798 }
3799 }
3800 return null;
3801 }
3802
Geoffrey Borggaard334c7e32013-08-08 14:31:36 -04003803 @Override
3804 public String getDeviceOwnerName() {
Amith Yamasani44a01b72013-09-16 10:44:57 -07003805 if (!mHasFeature) {
3806 return null;
3807 }
Geoffrey Borggaard334c7e32013-08-08 14:31:36 -04003808 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
3809 synchronized (this) {
3810 if (mDeviceOwner != null) {
Adam Connors776c5552014-01-09 10:42:56 +00003811 return mDeviceOwner.getDeviceOwnerName();
3812 }
3813 }
3814 return null;
3815 }
3816
Sander Alewijnse0ced6272014-08-26 11:18:26 +01003817 // Returns the active device owner or null if there is no device owner.
3818 private ActiveAdmin getDeviceOwnerAdmin() {
3819 String deviceOwnerPackageName = getDeviceOwner();
3820 if (deviceOwnerPackageName == null) {
3821 return null;
3822 }
3823
3824 DevicePolicyData policy = getUserData(UserHandle.USER_OWNER);
3825 final int n = policy.mAdminList.size();
3826 for (int i = 0; i < n; i++) {
3827 ActiveAdmin admin = policy.mAdminList.get(i);
3828 if (deviceOwnerPackageName.equals(admin.info.getPackageName())) {
3829 return admin;
3830 }
3831 }
3832 return null;
3833 }
3834
Adam Connors776c5552014-01-09 10:42:56 +00003835 @Override
Jason Monkb0dced82014-06-06 14:36:20 -04003836 public void clearDeviceOwner(String packageName) {
3837 if (packageName == null) {
3838 throw new NullPointerException("packageName is null");
3839 }
3840 try {
3841 int uid = mContext.getPackageManager().getPackageUid(packageName, 0);
3842 if (uid != Binder.getCallingUid()) {
3843 throw new SecurityException("Invalid packageName");
3844 }
3845 } catch (NameNotFoundException e) {
3846 throw new SecurityException(e);
3847 }
3848 if (!isDeviceOwner(packageName)) {
3849 throw new SecurityException("clearDeviceOwner can only be called by the device owner");
3850 }
3851 synchronized (this) {
3852 long ident = Binder.clearCallingIdentity();
3853 try {
Julia Reynolds3d9eb782014-08-11 16:40:08 -04003854 clearUserRestrictions(new UserHandle(UserHandle.USER_OWNER));
Jason Monkb0dced82014-06-06 14:36:20 -04003855 if (mDeviceOwner != null) {
3856 mDeviceOwner.clearDeviceOwner();
3857 mDeviceOwner.writeOwnerFile();
3858 }
3859 } finally {
3860 Binder.restoreCallingIdentity(ident);
3861 }
3862 }
3863 }
3864
3865 @Override
Amith Yamasanibf3a9462014-07-28 14:26:42 -07003866 public boolean setProfileOwner(ComponentName who, String ownerName, int userHandle) {
Adam Connors776c5552014-01-09 10:42:56 +00003867 if (!mHasFeature) {
3868 return false;
3869 }
Sudheer Shanka6c780ac2016-06-08 17:13:24 -07003870 if (ActivityManager.checkComponentPermission(android.Manifest.permission.CREATE_USERS,
3871 Binder.getCallingUid(), -1, true) == PackageManager.PERMISSION_DENIED) {
3872 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
3873 }
Adam Connors661ec472014-02-11 13:59:46 +00003874
Amith Yamasani29ce85b2014-09-03 17:30:43 -07003875 UserInfo info = mUserManager.getUserInfo(userHandle);
3876 if (info == null) {
Adam Connors661ec472014-02-11 13:59:46 +00003877 // User doesn't exist.
3878 throw new IllegalArgumentException(
3879 "Attempted to set profile owner for invalid userId: " + userHandle);
3880 }
Amith Yamasani29ce85b2014-09-03 17:30:43 -07003881 if (info.isGuest()) {
3882 throw new IllegalStateException("Cannot set a profile owner on a guest");
3883 }
Adam Connors661ec472014-02-11 13:59:46 +00003884
Amith Yamasanibf3a9462014-07-28 14:26:42 -07003885 if (who == null
3886 || !DeviceOwner.isInstalledForUser(who.getPackageName(), userHandle)) {
3887 throw new IllegalArgumentException("Component " + who
Adam Connors776c5552014-01-09 10:42:56 +00003888 + " not installed for userId:" + userHandle);
3889 }
3890 synchronized (this) {
Amith Yamasanibf3a9462014-07-28 14:26:42 -07003891 // Only SYSTEM_UID can override the userSetupComplete
3892 if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID
Amith Yamasanid616a332014-09-12 09:05:19 -07003893 && hasUserSetupCompleted(userHandle)) {
Adam Connors776c5552014-01-09 10:42:56 +00003894 throw new IllegalStateException(
3895 "Trying to set profile owner but user is already set-up.");
3896 }
Julia Reynolds401de172014-07-24 18:21:29 -04003897
Adam Connors776c5552014-01-09 10:42:56 +00003898 if (mDeviceOwner == null) {
3899 // Device owner state does not exist, create it.
Amith Yamasanibf3a9462014-07-28 14:26:42 -07003900 mDeviceOwner = DeviceOwner.createWithProfileOwner(who, ownerName,
Adam Connors776c5552014-01-09 10:42:56 +00003901 userHandle);
3902 mDeviceOwner.writeOwnerFile();
3903 return true;
3904 } else {
3905 // Device owner already exists, update it.
Amith Yamasanibf3a9462014-07-28 14:26:42 -07003906 mDeviceOwner.setProfileOwner(who, ownerName, userHandle);
Adam Connors776c5552014-01-09 10:42:56 +00003907 mDeviceOwner.writeOwnerFile();
3908 return true;
3909 }
3910 }
3911 }
3912
3913 @Override
Amith Yamasanibf3a9462014-07-28 14:26:42 -07003914 public void clearProfileOwner(ComponentName who) {
3915 if (!mHasFeature) {
3916 return;
3917 }
3918 UserHandle callingUser = Binder.getCallingUserHandle();
3919 // Check if this is the profile owner who is calling
3920 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
3921 synchronized (this) {
3922 long ident = Binder.clearCallingIdentity();
3923 try {
Julia Reynolds3d9eb782014-08-11 16:40:08 -04003924 clearUserRestrictions(callingUser);
Amith Yamasanibf3a9462014-07-28 14:26:42 -07003925 if (mDeviceOwner != null) {
3926 mDeviceOwner.removeProfileOwner(callingUser.getIdentifier());
3927 mDeviceOwner.writeOwnerFile();
3928 }
3929 } finally {
3930 Binder.restoreCallingIdentity(ident);
3931 }
3932 }
3933 }
3934
Julia Reynolds3d9eb782014-08-11 16:40:08 -04003935 private void clearUserRestrictions(UserHandle userHandle) {
3936 AudioManager audioManager =
3937 (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
3938 Bundle userRestrictions = mUserManager.getUserRestrictions();
3939 mUserManager.setUserRestrictions(new Bundle(), userHandle);
3940 if (userRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)) {
3941 audioManager.setMasterMute(false);
3942 }
3943 if (userRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE)) {
3944 audioManager.setMicrophoneMute(false);
3945 }
3946 }
3947
Amith Yamasanibf3a9462014-07-28 14:26:42 -07003948 @Override
3949 public boolean hasUserSetupCompleted() {
Amith Yamasanid616a332014-09-12 09:05:19 -07003950 return hasUserSetupCompleted(UserHandle.getCallingUserId());
3951 }
3952
3953 private boolean hasUserSetupCompleted(int userHandle) {
Amith Yamasanibf3a9462014-07-28 14:26:42 -07003954 if (!mHasFeature) {
3955 return true;
3956 }
Amith Yamasanid616a332014-09-12 09:05:19 -07003957 DevicePolicyData policy = getUserData(userHandle);
Amith Yamasanibf3a9462014-07-28 14:26:42 -07003958 // If policy is null, return true, else check if the setup has completed.
3959 return policy == null || policy.mUserSetupComplete;
3960 }
3961
3962 @Override
Alexandra Gherghina512675b2014-04-02 11:23:54 +01003963 public void setProfileEnabled(ComponentName who) {
3964 if (!mHasFeature) {
3965 return;
3966 }
Robin Lee65c27972014-08-28 16:56:15 +01003967 final int userHandle = UserHandle.getCallingUserId();
Alexandra Gherghina512675b2014-04-02 11:23:54 +01003968 synchronized (this) {
3969 // Check for permissions
3970 if (who == null) {
3971 throw new NullPointerException("ComponentName is null");
3972 }
3973 // Check if this is the profile owner who is calling
3974 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
Alexandra Gherghina385124d2014-04-03 13:37:39 +01003975 int userId = UserHandle.getCallingUserId();
Alexandra Gherghina512675b2014-04-02 11:23:54 +01003976
Alexandra Gherghina385124d2014-04-03 13:37:39 +01003977 long id = Binder.clearCallingIdentity();
Alexandra Gherghina512675b2014-04-02 11:23:54 +01003978 try {
Jessica Hummel91da58d2014-04-10 17:39:43 +01003979 mUserManager.setUserEnabled(userId);
Alexandra Gherghina512675b2014-04-02 11:23:54 +01003980 Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED);
Robin Lee65c27972014-08-28 16:56:15 +01003981 intent.putExtra(Intent.EXTRA_USER, new UserHandle(userHandle));
Alexandra Gherghina9944c2f2014-04-15 10:40:33 +01003982 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
3983 Intent.FLAG_RECEIVER_FOREGROUND);
Kenny Guy73a41d22014-06-05 16:51:24 +01003984 // TODO This should send to parent of profile (which is always owner at the moment).
Alexandra Gherghina512675b2014-04-02 11:23:54 +01003985 mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
3986 } finally {
3987 restoreCallingIdentity(id);
3988 }
3989 }
3990 }
3991
3992 @Override
Jessica Hummel1333ea12014-06-23 11:20:10 +01003993 public void setProfileName(ComponentName who, String profileName) {
3994 int userId = UserHandle.getCallingUserId();
3995
3996 if (who == null) {
3997 throw new NullPointerException("ComponentName is null");
3998 }
3999
4000 // Check if this is the profile owner (includes device owner).
4001 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
4002
4003 long id = Binder.clearCallingIdentity();
4004 try {
4005 mUserManager.setUserName(userId, profileName);
4006 } finally {
4007 restoreCallingIdentity(id);
4008 }
4009 }
4010
4011 @Override
Amith Yamasanibf3a9462014-07-28 14:26:42 -07004012 public ComponentName getProfileOwner(int userHandle) {
Adam Connors776c5552014-01-09 10:42:56 +00004013 if (!mHasFeature) {
4014 return null;
4015 }
4016
4017 synchronized (this) {
4018 if (mDeviceOwner != null) {
Amith Yamasanibf3a9462014-07-28 14:26:42 -07004019 return mDeviceOwner.getProfileOwnerComponent(userHandle);
Adam Connors776c5552014-01-09 10:42:56 +00004020 }
4021 }
4022 return null;
4023 }
4024
Adam Connors210fe212014-07-17 15:41:43 +01004025 // Returns the active profile owner for this user or null if the current user has no
4026 // profile owner.
4027 private ActiveAdmin getProfileOwnerAdmin(int userHandle) {
Amith Yamasanibf3a9462014-07-28 14:26:42 -07004028 ComponentName profileOwner =
4029 mDeviceOwner != null ? mDeviceOwner.getProfileOwnerComponent(userHandle) : null;
4030 if (profileOwner == null) {
Adam Connors210fe212014-07-17 15:41:43 +01004031 return null;
4032 }
4033
4034 DevicePolicyData policy = getUserData(userHandle);
4035 final int n = policy.mAdminList.size();
4036 for (int i = 0; i < n; i++) {
4037 ActiveAdmin admin = policy.mAdminList.get(i);
Rubin Xud7892e72014-10-30 17:57:23 +00004038 if (profileOwner.equals(admin.info.getComponent())) {
Adam Connors210fe212014-07-17 15:41:43 +01004039 return admin;
4040 }
4041 }
4042 return null;
4043 }
4044
Adam Connors776c5552014-01-09 10:42:56 +00004045 @Override
4046 public String getProfileOwnerName(int userHandle) {
4047 if (!mHasFeature) {
4048 return null;
4049 }
4050 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
4051
4052 synchronized (this) {
4053 if (mDeviceOwner != null) {
4054 return mDeviceOwner.getProfileOwnerName(userHandle);
Geoffrey Borggaard334c7e32013-08-08 14:31:36 -04004055 }
4056 }
4057 return null;
4058 }
4059
Esteban Talaverab5ef1622014-09-08 17:49:01 +01004060 /**
4061 * Device owner can only be set on an unprovisioned device, unless it was initiated by "adb", in
4062 * which case we allow it if no account is associated with the device.
4063 */
4064 private boolean allowedToSetDeviceOwnerOnDevice() {
4065 int callingId = Binder.getCallingUid();
4066 if (callingId == Process.SHELL_UID || callingId == Process.ROOT_UID) {
4067 return AccountManager.get(mContext).getAccounts().length == 0;
4068 } else {
Amith Yamasanid616a332014-09-12 09:05:19 -07004069 return !hasUserSetupCompleted(UserHandle.USER_OWNER);
Esteban Talaverab5ef1622014-09-08 17:49:01 +01004070 }
Amith Yamasani71e6c692013-03-24 17:39:28 -07004071 }
4072
Amith Yamasani599dd7c2012-09-14 23:20:08 -07004073 private void enforceCrossUserPermission(int userHandle) {
4074 if (userHandle < 0) {
4075 throw new IllegalArgumentException("Invalid userId " + userHandle);
4076 }
4077 final int callingUid = Binder.getCallingUid();
4078 if (userHandle == UserHandle.getUserId(callingUid)) return;
4079 if (callingUid != Process.SYSTEM_UID && callingUid != 0) {
4080 mContext.enforceCallingOrSelfPermission(
4081 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, "Must be system or have"
4082 + " INTERACT_ACROSS_USERS_FULL permission");
4083 }
4084 }
4085
Adam Connors210fe212014-07-17 15:41:43 +01004086 private void enforceSystemProcess(String message) {
4087 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
4088 throw new SecurityException(message);
4089 }
4090 }
4091
Jessica Hummel91da58d2014-04-10 17:39:43 +01004092 private void enforceNotManagedProfile(int userHandle, String message) {
4093 if(isManagedProfile(userHandle)) {
Robin Leea9e460a2014-05-21 15:04:19 +01004094 throw new SecurityException("You can not " + message + " for a managed profile. ");
Jessica Hummel91da58d2014-04-10 17:39:43 +01004095 }
4096 }
4097
4098 private UserInfo getProfileParent(int userHandle) {
4099 long ident = Binder.clearCallingIdentity();
4100 try {
4101 return mUserManager.getProfileParent(userHandle);
4102 } finally {
4103 Binder.restoreCallingIdentity(ident);
4104 }
4105 }
4106
4107 private boolean isManagedProfile(int userHandle) {
4108 long ident = Binder.clearCallingIdentity();
4109 try {
4110 return mUserManager.getUserInfo(userHandle).isManagedProfile();
4111 } finally {
4112 Binder.restoreCallingIdentity(ident);
4113 }
4114 }
4115
Amith Yamasani71e6c692013-03-24 17:39:28 -07004116 private void enableIfNecessary(String packageName, int userId) {
4117 try {
4118 IPackageManager ipm = AppGlobals.getPackageManager();
4119 ApplicationInfo ai = ipm.getApplicationInfo(packageName,
4120 PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
4121 userId);
4122 if (ai.enabledSetting
4123 == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
4124 ipm.setApplicationEnabledSetting(packageName,
4125 PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
Dianne Hackborn3fa3c28a2013-03-26 16:15:41 -07004126 PackageManager.DONT_KILL_APP, userId, "DevicePolicyManager");
Amith Yamasani71e6c692013-03-24 17:39:28 -07004127 }
4128 } catch (RemoteException e) {
4129 }
4130 }
4131
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08004132 @Override
4133 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
4134 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
4135 != PackageManager.PERMISSION_GRANTED) {
4136
4137 pw.println("Permission Denial: can't dump DevicePolicyManagerService from from pid="
4138 + Binder.getCallingPid()
4139 + ", uid=" + Binder.getCallingUid());
4140 return;
4141 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07004142
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08004143 final Printer p = new PrintWriterPrinter(pw);
Konstantin Lopyrev32558232010-05-20 16:18:05 -07004144
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08004145 synchronized (this) {
4146 p.println("Current Device Policy Manager state:");
Konstantin Lopyrev32558232010-05-20 16:18:05 -07004147
Amith Yamasani599dd7c2012-09-14 23:20:08 -07004148 int userCount = mUserData.size();
4149 for (int u = 0; u < userCount; u++) {
4150 DevicePolicyData policy = getUserData(mUserData.keyAt(u));
4151 p.println(" Enabled Device Admins (User " + policy.mUserHandle + "):");
4152 final int N = policy.mAdminList.size();
4153 for (int i=0; i<N; i++) {
4154 ActiveAdmin ap = policy.mAdminList.get(i);
4155 if (ap != null) {
4156 pw.print(" "); pw.print(ap.info.getComponent().flattenToShortString());
4157 pw.println(":");
4158 ap.dump(" ", pw);
4159 }
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08004160 }
Fyodor Kupolov96fb9322014-12-01 15:08:09 -08004161 if (!policy.mRemovingAdmins.isEmpty()) {
4162 p.println(" Removing Device Admins (User " + policy.mUserHandle + "): "
4163 + policy.mRemovingAdmins);
4164 }
Konstantin Lopyrev32558232010-05-20 16:18:05 -07004165
Amith Yamasani599dd7c2012-09-14 23:20:08 -07004166 pw.println(" ");
4167 pw.print(" mPasswordOwner="); pw.println(policy.mPasswordOwner);
4168 }
Dianne Hackborn87bba1e2010-02-26 17:25:54 -08004169 }
4170 }
Sander Alewijnsef475ca32014-02-17 15:13:58 +00004171
Adam Connors010cfd42014-04-16 12:48:13 +01004172 @Override
Robin Lee5c921da2014-03-24 15:11:35 +00004173 public void addPersistentPreferredActivity(ComponentName who, IntentFilter filter,
Sander Alewijnsef475ca32014-02-17 15:13:58 +00004174 ComponentName activity) {
Robin Lee65c27972014-08-28 16:56:15 +01004175 final int userHandle = UserHandle.getCallingUserId();
4176
Sander Alewijnsef475ca32014-02-17 15:13:58 +00004177 synchronized (this) {
Robin Lee5c921da2014-03-24 15:11:35 +00004178 if (who == null) {
4179 throw new NullPointerException("ComponentName is null");
4180 }
4181 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
4182
4183 IPackageManager pm = AppGlobals.getPackageManager();
4184 long id = Binder.clearCallingIdentity();
4185 try {
Robin Lee65c27972014-08-28 16:56:15 +01004186 pm.addPersistentPreferredActivity(filter, activity, userHandle);
Robin Lee5c921da2014-03-24 15:11:35 +00004187 } catch (RemoteException re) {
4188 // Shouldn't happen
4189 } finally {
4190 restoreCallingIdentity(id);
Sander Alewijnsef475ca32014-02-17 15:13:58 +00004191 }
4192 }
4193 }
4194
Adam Connors010cfd42014-04-16 12:48:13 +01004195 @Override
Robin Lee5c921da2014-03-24 15:11:35 +00004196 public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
Robin Lee65c27972014-08-28 16:56:15 +01004197 final int userHandle = UserHandle.getCallingUserId();
4198
Sander Alewijnsef475ca32014-02-17 15:13:58 +00004199 synchronized (this) {
Robin Lee5c921da2014-03-24 15:11:35 +00004200 if (who == null) {
4201 throw new NullPointerException("ComponentName is null");
4202 }
4203 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
4204
4205 IPackageManager pm = AppGlobals.getPackageManager();
4206 long id = Binder.clearCallingIdentity();
4207 try {
Robin Lee65c27972014-08-28 16:56:15 +01004208 pm.clearPackagePersistentPreferredActivities(packageName, userHandle);
Robin Lee5c921da2014-03-24 15:11:35 +00004209 } catch (RemoteException re) {
4210 // Shouldn't happen
4211 } finally {
4212 restoreCallingIdentity(id);
Sander Alewijnsef475ca32014-02-17 15:13:58 +00004213 }
4214 }
4215 }
Robin Lee66e5d962014-04-09 16:44:21 +01004216
4217 @Override
4218 public void setApplicationRestrictions(ComponentName who, String packageName, Bundle settings) {
4219 final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
4220
4221 synchronized (this) {
4222 if (who == null) {
4223 throw new NullPointerException("ComponentName is null");
4224 }
4225 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
4226
Robin Lee66e5d962014-04-09 16:44:21 +01004227 long id = Binder.clearCallingIdentity();
4228 try {
Jessica Hummel91da58d2014-04-10 17:39:43 +01004229 mUserManager.setApplicationRestrictions(packageName, settings, userHandle);
Robin Lee66e5d962014-04-09 16:44:21 +01004230 } finally {
4231 restoreCallingIdentity(id);
4232 }
4233 }
4234 }
4235
Jim Millere303bf42014-08-26 17:12:29 -07004236 public void setTrustAgentConfiguration(ComponentName admin, ComponentName agent,
4237 PersistableBundle args, int userHandle) {
Jim Miller604e7552014-07-18 19:00:02 -07004238 if (!mHasFeature) {
4239 return;
4240 }
4241 enforceCrossUserPermission(userHandle);
Jim Millere303bf42014-08-26 17:12:29 -07004242 enforceNotManagedProfile(userHandle, "set trust agent configuration");
Jim Miller604e7552014-07-18 19:00:02 -07004243 synchronized (this) {
4244 if (admin == null) {
4245 throw new NullPointerException("admin is null");
4246 }
4247 if (agent == null) {
4248 throw new NullPointerException("agent is null");
4249 }
4250 ActiveAdmin ap = getActiveAdminForCallerLocked(admin,
4251 DeviceAdminInfo.USES_POLICY_DISABLE_KEYGUARD_FEATURES);
Jim Millere303bf42014-08-26 17:12:29 -07004252 ap.trustAgentInfos.put(agent.flattenToString(), new TrustAgentInfo(args));
Jim Miller604e7552014-07-18 19:00:02 -07004253 saveSettingsLocked(userHandle);
4254 syncDeviceCapabilitiesLocked(getUserData(userHandle));
4255 }
4256 }
4257
Jim Millere303bf42014-08-26 17:12:29 -07004258 public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin,
4259 ComponentName agent, int userHandle) {
Jim Miller604e7552014-07-18 19:00:02 -07004260 if (!mHasFeature) {
4261 return null;
4262 }
4263 enforceCrossUserPermission(userHandle);
Jim Millere303bf42014-08-26 17:12:29 -07004264 if (agent == null) {
4265 throw new NullPointerException("agent is null");
4266 }
4267
Jim Miller604e7552014-07-18 19:00:02 -07004268 synchronized (this) {
Jim Miller604e7552014-07-18 19:00:02 -07004269 final String componentName = agent.flattenToString();
4270 if (admin != null) {
4271 final ActiveAdmin ap = getActiveAdminUncheckedLocked(admin, userHandle);
Jim Millere303bf42014-08-26 17:12:29 -07004272 if (ap == null) return null;
4273 TrustAgentInfo trustAgentInfo = ap.trustAgentInfos.get(componentName);
4274 if (trustAgentInfo == null || trustAgentInfo.options == null) return null;
4275 List<PersistableBundle> result = new ArrayList<PersistableBundle>();
4276 result.add(trustAgentInfo.options);
4277 return result;
Jim Miller604e7552014-07-18 19:00:02 -07004278 }
4279
4280 // Return strictest policy for this user and profiles that are visible from this user.
Jim Millere303bf42014-08-26 17:12:29 -07004281 final List<UserInfo> profiles = mUserManager.getProfiles(userHandle);
4282 List<PersistableBundle> result = null;
4283
4284 // Search through all admins that use KEYGUARD_DISABLE_TRUST_AGENTS and keep track
4285 // of the options. If any admin doesn't have options, discard options for the rest
4286 // and return null.
4287 boolean allAdminsHaveOptions = true;
Jim Miller604e7552014-07-18 19:00:02 -07004288 for (UserInfo userInfo : profiles) {
Benjamin Franzfadb2b32015-01-14 18:22:42 +00004289 DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
Jim Miller604e7552014-07-18 19:00:02 -07004290 final int N = policy.mAdminList.size();
Jim Millere303bf42014-08-26 17:12:29 -07004291 for (int i=0; i < N; i++) {
4292 final ActiveAdmin active = policy.mAdminList.get(i);
4293 final boolean disablesTrust = (active.disabledKeyguardFeatures
4294 & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
4295 final TrustAgentInfo info = active.trustAgentInfos.get(componentName);
4296 if (info != null && info.options != null && !info.options.isEmpty()) {
4297 if (disablesTrust) {
4298 if (result == null) {
4299 result = new ArrayList<PersistableBundle>();
Jim Miller604e7552014-07-18 19:00:02 -07004300 }
Jim Millere303bf42014-08-26 17:12:29 -07004301 result.add(info.options);
Jim Miller604e7552014-07-18 19:00:02 -07004302 } else {
Jim Millere303bf42014-08-26 17:12:29 -07004303 Log.w(LOG_TAG, "Ignoring admin " + active.info
4304 + " because it has trust options but doesn't declare "
4305 + "KEYGUARD_DISABLE_TRUST_AGENTS");
Jim Miller604e7552014-07-18 19:00:02 -07004306 }
Jim Millere303bf42014-08-26 17:12:29 -07004307 } else if (disablesTrust) {
4308 allAdminsHaveOptions = false;
4309 break;
Jim Miller604e7552014-07-18 19:00:02 -07004310 }
4311 }
4312 }
Jim Millere303bf42014-08-26 17:12:29 -07004313 return allAdminsHaveOptions ? result : null;
Jim Miller604e7552014-07-18 19:00:02 -07004314 }
4315 }
4316
Amith Yamasanif20d6402014-05-24 15:34:37 -07004317 @Override
4318 public void setRestrictionsProvider(ComponentName who, ComponentName permissionProvider) {
4319 synchronized (this) {
4320 if (who == null) {
4321 throw new NullPointerException("ComponentName is null");
4322 }
4323 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
4324
4325 int userHandle = UserHandle.getCallingUserId();
4326 DevicePolicyData userData = getUserData(userHandle);
4327 userData.mRestrictionsProvider = permissionProvider;
4328 saveSettingsLocked(userHandle);
4329 }
4330 }
4331
4332 @Override
4333 public ComponentName getRestrictionsProvider(int userHandle) {
4334 synchronized (this) {
4335 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
4336 throw new SecurityException("Only the system can query the permission provider");
4337 }
4338 DevicePolicyData userData = getUserData(userHandle);
4339 return userData != null ? userData.mRestrictionsProvider : null;
4340 }
4341 }
4342
Nicolas Prevot81948992014-05-16 18:25:26 +01004343 public void addCrossProfileIntentFilter(ComponentName who, IntentFilter filter, int flags) {
Nicolas Prevot10fa67c2014-03-24 13:44:38 +00004344 int callingUserId = UserHandle.getCallingUserId();
4345 synchronized (this) {
4346 if (who == null) {
4347 throw new NullPointerException("ComponentName is null");
4348 }
4349 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
4350
4351 IPackageManager pm = AppGlobals.getPackageManager();
4352 long id = Binder.clearCallingIdentity();
4353 try {
Nicolas Prevot81948992014-05-16 18:25:26 +01004354 if ((flags & DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED) != 0) {
Nicolas Prevot3f7777f2014-07-24 15:58:39 +01004355 pm.addCrossProfileIntentFilter(filter, who.getPackageName(),
4356 mContext.getUserId(), callingUserId, UserHandle.USER_OWNER, 0);
Nicolas Prevot10fa67c2014-03-24 13:44:38 +00004357 }
Nicolas Prevot81948992014-05-16 18:25:26 +01004358 if ((flags & DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT) != 0) {
Nicolas Prevot3f7777f2014-07-24 15:58:39 +01004359 pm.addCrossProfileIntentFilter(filter, who.getPackageName(),
4360 mContext.getUserId(), UserHandle.USER_OWNER, callingUserId, 0);
Nicolas Prevot10fa67c2014-03-24 13:44:38 +00004361 }
4362 } catch (RemoteException re) {
4363 // Shouldn't happen
4364 } finally {
4365 restoreCallingIdentity(id);
4366 }
4367 }
4368 }
4369
Nicolas Prevot81948992014-05-16 18:25:26 +01004370 public void clearCrossProfileIntentFilters(ComponentName who) {
Nicolas Prevot10fa67c2014-03-24 13:44:38 +00004371 int callingUserId = UserHandle.getCallingUserId();
4372 synchronized (this) {
4373 if (who == null) {
4374 throw new NullPointerException("ComponentName is null");
4375 }
4376 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
4377 IPackageManager pm = AppGlobals.getPackageManager();
4378 long id = Binder.clearCallingIdentity();
4379 try {
Nicolas Prevot3f7777f2014-07-24 15:58:39 +01004380 pm.clearCrossProfileIntentFilters(callingUserId, who.getPackageName(),
4381 callingUserId);
Nicolas Prevot63798c52014-05-27 13:22:38 +01004382 // If we want to support multiple managed profiles, we will have to only remove
4383 // those that have callingUserId as their target.
Nicolas Prevot3f7777f2014-07-24 15:58:39 +01004384 pm.clearCrossProfileIntentFilters(UserHandle.USER_OWNER, who.getPackageName(),
4385 callingUserId);
Nicolas Prevot10fa67c2014-03-24 13:44:38 +00004386 } catch (RemoteException re) {
4387 // Shouldn't happen
4388 } finally {
4389 restoreCallingIdentity(id);
4390 }
4391 }
4392 }
4393
Kenny Guyfa80a4f2014-08-20 19:40:59 +01004394 /**
4395 * @return true if all packages in enabledPackages are either in the list
4396 * permittedList or are a system app.
4397 */
4398 private boolean checkPackagesInPermittedListOrSystem(List<String> enabledPackages,
4399 List<String> permittedList) {
4400 int userIdToCheck = UserHandle.getCallingUserId();
4401 long id = Binder.clearCallingIdentity();
4402 try {
4403 // If we have an enabled packages list for a managed profile the packages
4404 // we should check are installed for the parent user.
4405 UserInfo user = mUserManager.getUserInfo(userIdToCheck);
4406 if (user.isManagedProfile()) {
4407 userIdToCheck = user.profileGroupId;
4408 }
4409
4410 IPackageManager pm = AppGlobals.getPackageManager();
4411 for (String enabledPackage : enabledPackages) {
4412 boolean systemService = false;
4413 try {
4414 ApplicationInfo applicationInfo = pm.getApplicationInfo(enabledPackage,
4415 PackageManager.GET_UNINSTALLED_PACKAGES, userIdToCheck);
4416 systemService = (applicationInfo.flags
4417 & ApplicationInfo.FLAG_SYSTEM) != 0;
4418 } catch (RemoteException e) {
4419 Log.i(LOG_TAG, "Can't talk to package managed", e);
4420 }
4421 if (!systemService && !permittedList.contains(enabledPackage)) {
4422 return false;
4423 }
4424 }
4425 } finally {
4426 restoreCallingIdentity(id);
4427 }
4428 return true;
4429 }
4430
4431 private AccessibilityManager getAccessibilityManagerForUser(int userId) {
4432 // Not using AccessibilityManager.getInstance because that guesses
4433 // at the user you require based on callingUid and caches for a given
4434 // process.
4435 IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
4436 IAccessibilityManager service = iBinder == null
4437 ? null : IAccessibilityManager.Stub.asInterface(iBinder);
4438 return new AccessibilityManager(mContext, service, userId);
4439 }
4440
4441 @Override
4442 public boolean setPermittedAccessibilityServices(ComponentName who, List packageList) {
4443 if (!mHasFeature) {
4444 return false;
4445 }
4446 if (who == null) {
4447 throw new NullPointerException("ComponentName is null");
4448 }
4449
4450 if (packageList != null) {
4451 int userId = UserHandle.getCallingUserId();
4452 List<AccessibilityServiceInfo> enabledServices = null;
4453 long id = Binder.clearCallingIdentity();
4454 try {
4455 UserInfo user = mUserManager.getUserInfo(userId);
4456 if (user.isManagedProfile()) {
4457 userId = user.profileGroupId;
4458 }
4459 AccessibilityManager accessibilityManager = getAccessibilityManagerForUser(userId);
4460 enabledServices = accessibilityManager.getEnabledAccessibilityServiceList(
4461 AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
4462 } finally {
4463 restoreCallingIdentity(id);
4464 }
4465
4466 if (enabledServices != null) {
4467 List<String> enabledPackages = new ArrayList<String>();
4468 for (AccessibilityServiceInfo service : enabledServices) {
4469 enabledPackages.add(service.getResolveInfo().serviceInfo.packageName);
4470 }
4471 if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList)) {
4472 Slog.e(LOG_TAG, "Cannot set permitted accessibility services, "
4473 + "because it contains already enabled accesibility services.");
4474 return false;
4475 }
4476 }
4477 }
4478
4479 synchronized (this) {
4480 ActiveAdmin admin = getActiveAdminForCallerLocked(who,
4481 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
4482 admin.permittedAccessiblityServices = packageList;
4483 saveSettingsLocked(UserHandle.getCallingUserId());
4484 }
4485 return true;
4486 }
4487
4488 @Override
4489 public List getPermittedAccessibilityServices(ComponentName who) {
4490 if (!mHasFeature) {
4491 return null;
4492 }
4493
4494 if (who == null) {
4495 throw new NullPointerException("ComponentName is null");
4496 }
4497
4498 synchronized (this) {
4499 ActiveAdmin admin = getActiveAdminForCallerLocked(who,
4500 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
4501 return admin.permittedAccessiblityServices;
4502 }
4503 }
4504
4505 @Override
4506 public List getPermittedAccessibilityServicesForUser(int userId) {
4507 if (!mHasFeature) {
4508 return null;
4509 }
4510 synchronized (this) {
4511 List<String> result = null;
4512 // If we have multiple profiles we return the intersection of the
4513 // permitted lists. This can happen in cases where we have a device
4514 // and profile owner.
4515 List<UserInfo> profiles = mUserManager.getProfiles(userId);
4516 final int PROFILES_SIZE = profiles.size();
4517 for (int i = 0; i < PROFILES_SIZE; ++i) {
4518 // Just loop though all admins, only device or profiles
4519 // owners can have permitted lists set.
Benjamin Franzfadb2b32015-01-14 18:22:42 +00004520 DevicePolicyData policy = getUserDataUnchecked(profiles.get(i).id);
Kenny Guyfa80a4f2014-08-20 19:40:59 +01004521 final int N = policy.mAdminList.size();
4522 for (int j = 0; j < N; j++) {
4523 ActiveAdmin admin = policy.mAdminList.get(j);
4524 List<String> fromAdmin = admin.permittedAccessiblityServices;
4525 if (fromAdmin != null) {
4526 if (result == null) {
4527 result = new ArrayList<String>(fromAdmin);
4528 } else {
4529 result.retainAll(fromAdmin);
4530 }
4531 }
4532 }
4533 }
4534
4535 // If we have a permitted list add all system accessibility services.
4536 if (result != null) {
4537 long id = Binder.clearCallingIdentity();
4538 try {
4539 UserInfo user = mUserManager.getUserInfo(userId);
4540 if (user.isManagedProfile()) {
4541 userId = user.profileGroupId;
4542 }
4543 AccessibilityManager accessibilityManager =
4544 getAccessibilityManagerForUser(userId);
4545 List<AccessibilityServiceInfo> installedServices =
4546 accessibilityManager.getInstalledAccessibilityServiceList();
4547
4548 IPackageManager pm = AppGlobals.getPackageManager();
4549 if (installedServices != null) {
4550 for (AccessibilityServiceInfo service : installedServices) {
4551 String packageName = service.getResolveInfo().serviceInfo.packageName;
4552 try {
4553 ApplicationInfo applicationInfo = pm.getApplicationInfo(packageName,
4554 PackageManager.GET_UNINSTALLED_PACKAGES, userId);
4555 if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4556 result.add(packageName);
4557 }
4558 } catch (RemoteException e) {
4559 Log.i(LOG_TAG, "Accessibility service in missing package", e);
4560 }
4561 }
4562 }
4563 } finally {
4564 restoreCallingIdentity(id);
4565 }
4566 }
4567
4568 return result;
4569 }
4570 }
4571
4572 private boolean checkCallerIsCurrentUserOrProfile() {
4573 int callingUserId = UserHandle.getCallingUserId();
4574 long token = Binder.clearCallingIdentity();
4575 try {
4576 UserInfo currentUser;
4577 UserInfo callingUser = mUserManager.getUserInfo(callingUserId);
4578 try {
4579 currentUser = ActivityManagerNative.getDefault().getCurrentUser();
4580 } catch (RemoteException e) {
4581 Slog.e(LOG_TAG, "Failed to talk to activity managed.", e);
4582 return false;
4583 }
4584
4585 if (callingUser.isManagedProfile() && callingUser.profileGroupId != currentUser.id) {
4586 Slog.e(LOG_TAG, "Cannot set permitted input methods for managed profile "
4587 + "of a user that isn't the foreground user.");
4588 return false;
4589 }
4590 if (!callingUser.isManagedProfile() && callingUserId != currentUser.id ) {
4591 Slog.e(LOG_TAG, "Cannot set permitted input methods "
4592 + "of a user that isn't the foreground user.");
4593 return false;
4594 }
4595 } finally {
4596 Binder.restoreCallingIdentity(token);
4597 }
4598 return true;
4599 }
4600
4601 @Override
4602 public boolean setPermittedInputMethods(ComponentName who, List packageList) {
4603 if (!mHasFeature) {
4604 return false;
4605 }
4606 if (who == null) {
4607 throw new NullPointerException("ComponentName is null");
4608 }
4609
4610 // TODO When InputMethodManager supports per user calls remove
4611 // this restriction.
4612 if (!checkCallerIsCurrentUserOrProfile()) {
4613 return false;
4614 }
4615
4616 if (packageList != null) {
4617 // InputMethodManager fetches input methods for current user.
4618 // So this can only be set when calling user is the current user
4619 // or parent is current user in case of managed profiles.
4620 InputMethodManager inputMethodManager = (InputMethodManager) mContext
4621 .getSystemService(Context.INPUT_METHOD_SERVICE);
4622 List<InputMethodInfo> enabledImes = inputMethodManager.getEnabledInputMethodList();
4623
4624 if (enabledImes != null) {
4625 List<String> enabledPackages = new ArrayList<String>();
4626 for (InputMethodInfo ime : enabledImes) {
4627 enabledPackages.add(ime.getPackageName());
4628 }
4629 if (!checkPackagesInPermittedListOrSystem(enabledPackages, packageList)) {
4630 Slog.e(LOG_TAG, "Cannot set permitted input methods, "
4631 + "because it contains already enabled input method.");
4632 return false;
4633 }
4634 }
4635 }
4636
4637 synchronized (this) {
4638 ActiveAdmin admin = getActiveAdminForCallerLocked(who,
4639 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
4640 admin.permittedInputMethods = packageList;
4641 saveSettingsLocked(UserHandle.getCallingUserId());
4642 }
4643 return true;
4644 }
4645
4646 @Override
4647 public List getPermittedInputMethods(ComponentName who) {
4648 if (!mHasFeature) {
4649 return null;
4650 }
4651
4652 if (who == null) {
4653 throw new NullPointerException("ComponentName is null");
4654 }
4655
4656 synchronized (this) {
4657 ActiveAdmin admin = getActiveAdminForCallerLocked(who,
4658 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
4659 return admin.permittedInputMethods;
4660 }
4661 }
4662
4663 @Override
4664 public List getPermittedInputMethodsForCurrentUser() {
4665 UserInfo currentUser;
4666 try {
4667 currentUser = ActivityManagerNative.getDefault().getCurrentUser();
4668 } catch (RemoteException e) {
4669 Slog.e(LOG_TAG, "Failed to make remote calls to get current user", e);
4670 // Activity managed is dead, just allow all IMEs
4671 return null;
4672 }
4673
4674 int userId = currentUser.id;
4675 synchronized (this) {
4676 List<String> result = null;
4677 // If we have multiple profiles we return the intersection of the
4678 // permitted lists. This can happen in cases where we have a device
4679 // and profile owner.
4680 List<UserInfo> profiles = mUserManager.getProfiles(userId);
4681 final int PROFILES_SIZE = profiles.size();
4682 for (int i = 0; i < PROFILES_SIZE; ++i) {
4683 // Just loop though all admins, only device or profiles
4684 // owners can have permitted lists set.
Benjamin Franzfadb2b32015-01-14 18:22:42 +00004685 DevicePolicyData policy = getUserDataUnchecked(profiles.get(i).id);
Kenny Guyfa80a4f2014-08-20 19:40:59 +01004686 final int N = policy.mAdminList.size();
4687 for (int j = 0; j < N; j++) {
4688 ActiveAdmin admin = policy.mAdminList.get(j);
4689 List<String> fromAdmin = admin.permittedInputMethods;
4690 if (fromAdmin != null) {
4691 if (result == null) {
4692 result = new ArrayList<String>(fromAdmin);
4693 } else {
4694 result.retainAll(fromAdmin);
4695 }
4696 }
4697 }
4698 }
4699
4700 // If we have a permitted list add all system input methods.
4701 if (result != null) {
4702 InputMethodManager inputMethodManager = (InputMethodManager) mContext
4703 .getSystemService(Context.INPUT_METHOD_SERVICE);
4704 List<InputMethodInfo> imes = inputMethodManager.getInputMethodList();
4705 long id = Binder.clearCallingIdentity();
4706 try {
4707 IPackageManager pm = AppGlobals.getPackageManager();
4708 if (imes != null) {
4709 for (InputMethodInfo ime : imes) {
4710 String packageName = ime.getPackageName();
4711 try {
4712 ApplicationInfo applicationInfo = pm.getApplicationInfo(
4713 packageName, PackageManager.GET_UNINSTALLED_PACKAGES,
4714 userId);
4715 if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
4716 result.add(packageName);
4717 }
4718 } catch (RemoteException e) {
4719 Log.i(LOG_TAG, "Input method for missing package", e);
4720 }
4721 }
4722 }
4723 } finally {
4724 restoreCallingIdentity(id);
4725 }
4726 }
4727 return result;
4728 }
4729 }
4730
Robin Lee66e5d962014-04-09 16:44:21 +01004731 @Override
Julia Reynolds1e958392014-05-16 14:25:21 -04004732 public UserHandle createUser(ComponentName who, String name) {
4733 synchronized (this) {
4734 if (who == null) {
4735 throw new NullPointerException("ComponentName is null");
4736 }
4737 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
4738
4739 long id = Binder.clearCallingIdentity();
4740 try {
4741 UserInfo userInfo = mUserManager.createUser(name, 0 /* flags */);
4742 if (userInfo != null) {
4743 return userInfo.getUserHandle();
4744 }
4745 return null;
4746 } finally {
4747 restoreCallingIdentity(id);
4748 }
4749 }
4750 }
4751
4752 @Override
Jason Monk03978a42014-06-10 15:05:30 -04004753 public UserHandle createAndInitializeUser(ComponentName who, String name,
4754 String ownerName, ComponentName profileOwnerComponent, Bundle adminExtras) {
4755 UserHandle user = createUser(who, name);
Benjamin Franzf87b1742015-01-23 15:32:30 +00004756 if (user == null) {
4757 return null;
4758 }
Jason Monk03978a42014-06-10 15:05:30 -04004759 long id = Binder.clearCallingIdentity();
4760 try {
4761 String profileOwnerPkg = profileOwnerComponent.getPackageName();
4762 final IPackageManager ipm = AppGlobals.getPackageManager();
4763 IActivityManager activityManager = ActivityManagerNative.getDefault();
4764
4765 try {
4766 // Install the profile owner if not present.
4767 if (!ipm.isPackageAvailable(profileOwnerPkg, user.getIdentifier())) {
4768 ipm.installExistingPackageAsUser(profileOwnerPkg, user.getIdentifier());
4769 }
4770
4771 // Start user in background.
4772 activityManager.startUserInBackground(user.getIdentifier());
4773 } catch (RemoteException e) {
4774 Slog.e(LOG_TAG, "Failed to make remote calls for configureUser", e);
4775 }
4776
4777 setActiveAdmin(profileOwnerComponent, true, user.getIdentifier(), adminExtras);
Amith Yamasanibf3a9462014-07-28 14:26:42 -07004778 setProfileOwner(profileOwnerComponent, ownerName, user.getIdentifier());
Jason Monk03978a42014-06-10 15:05:30 -04004779 return user;
4780 } finally {
4781 restoreCallingIdentity(id);
4782 }
4783 }
4784
4785 @Override
Julia Reynolds1e958392014-05-16 14:25:21 -04004786 public boolean removeUser(ComponentName who, UserHandle userHandle) {
4787 synchronized (this) {
4788 if (who == null) {
4789 throw new NullPointerException("ComponentName is null");
4790 }
4791 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
4792
4793 long id = Binder.clearCallingIdentity();
4794 try {
4795 return mUserManager.removeUser(userHandle.getIdentifier());
4796 } finally {
4797 restoreCallingIdentity(id);
4798 }
4799 }
4800 }
4801
4802 @Override
Jason Monk582d9112014-07-09 19:57:08 -04004803 public boolean switchUser(ComponentName who, UserHandle userHandle) {
4804 synchronized (this) {
4805 if (who == null) {
4806 throw new NullPointerException("ComponentName is null");
4807 }
4808 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
4809
4810 long id = Binder.clearCallingIdentity();
4811 try {
4812 int userId = UserHandle.USER_OWNER;
4813 if (userHandle != null) {
4814 userId = userHandle.getIdentifier();
4815 }
4816 return ActivityManagerNative.getDefault().switchUser(userId);
4817 } catch (RemoteException e) {
4818 Log.e(LOG_TAG, "Couldn't switch user", e);
4819 return false;
4820 } finally {
4821 restoreCallingIdentity(id);
4822 }
4823 }
4824 }
4825
4826 @Override
Robin Lee66e5d962014-04-09 16:44:21 +01004827 public Bundle getApplicationRestrictions(ComponentName who, String packageName) {
4828 final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
4829
4830 synchronized (this) {
4831 if (who == null) {
4832 throw new NullPointerException("ComponentName is null");
4833 }
4834 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
4835
Robin Lee66e5d962014-04-09 16:44:21 +01004836 long id = Binder.clearCallingIdentity();
4837 try {
Jessica Hummel91da58d2014-04-10 17:39:43 +01004838 return mUserManager.getApplicationRestrictions(packageName, userHandle);
Robin Lee66e5d962014-04-09 16:44:21 +01004839 } finally {
4840 restoreCallingIdentity(id);
4841 }
4842 }
4843 }
Amith Yamasanibe465322014-04-24 13:45:17 -07004844
4845 @Override
4846 public void setUserRestriction(ComponentName who, String key, boolean enabled) {
Amith Yamasani8cd28b52014-06-08 17:54:27 -07004847 final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
4848 final int userHandle = user.getIdentifier();
Amith Yamasanibe465322014-04-24 13:45:17 -07004849 synchronized (this) {
4850 if (who == null) {
4851 throw new NullPointerException("ComponentName is null");
4852 }
Julia Reynolds2cb384f2014-08-13 15:15:55 -04004853 ActiveAdmin activeAdmin =
4854 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
4855 boolean isDeviceOwner = isDeviceOwner(activeAdmin.info.getPackageName());
Amith Yamasanic34dc7c2014-09-18 09:42:42 -07004856 if (!isDeviceOwner && userHandle != UserHandle.USER_OWNER
4857 && DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) {
Julia Reynolds2cb384f2014-08-13 15:15:55 -04004858 throw new SecurityException("Profile owners cannot set user restriction " + key);
4859 }
Amith Yamasani8cd28b52014-06-08 17:54:27 -07004860 boolean alreadyRestricted = mUserManager.hasUserRestriction(key, user);
Amith Yamasanibe465322014-04-24 13:45:17 -07004861
Julia Reynoldsb53453f2014-08-22 11:42:43 -04004862 IAudioService iAudioService = null;
4863 if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)
4864 || UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
4865 iAudioService = IAudioService.Stub.asInterface(
4866 ServiceManager.getService(Context.AUDIO_SERVICE));
4867 }
4868
4869 if (enabled && !alreadyRestricted) {
4870 try {
4871 if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
4872 iAudioService.setMicrophoneMute(true, who.getPackageName());
4873 } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
4874 iAudioService.setMasterMute(true, 0, who.getPackageName(), null);
4875 }
4876 } catch (RemoteException re) {
4877 Slog.e(LOG_TAG, "Failed to talk to AudioService.", re);
4878 }
4879 }
Amith Yamasanibe465322014-04-24 13:45:17 -07004880 long id = Binder.clearCallingIdentity();
4881 try {
Julia Reynolds3d9eb782014-08-11 16:40:08 -04004882 if (enabled && !alreadyRestricted) {
4883 if (UserManager.DISALLOW_CONFIG_WIFI.equals(key)) {
4884 Settings.Secure.putIntForUser(mContext.getContentResolver(),
4885 Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0,
Amith Yamasani8cd28b52014-06-08 17:54:27 -07004886 userHandle);
Julia Reynolds3d9eb782014-08-11 16:40:08 -04004887 } else if (UserManager.DISALLOW_USB_FILE_TRANSFER.equals(key)) {
4888 UsbManager manager =
4889 (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
4890 manager.setCurrentFunction("none", false);
4891 } else if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
4892 Settings.Secure.putIntForUser(mContext.getContentResolver(),
4893 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF,
Amith Yamasani8cd28b52014-06-08 17:54:27 -07004894 userHandle);
Julia Reynolds3d9eb782014-08-11 16:40:08 -04004895 Settings.Secure.putStringForUser(mContext.getContentResolver(),
4896 Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "",
Amith Yamasani8cd28b52014-06-08 17:54:27 -07004897 userHandle);
Julia Reynolds3d9eb782014-08-11 16:40:08 -04004898 } else if (UserManager.DISALLOW_DEBUGGING_FEATURES.equals(key)) {
Amith Yamasani8cd28b52014-06-08 17:54:27 -07004899 // Only disable adb if changing for primary user, since it is global
4900 if (userHandle == UserHandle.USER_OWNER) {
4901 Settings.Global.putStringForUser(mContext.getContentResolver(),
4902 Settings.Global.ADB_ENABLED, "0", userHandle);
4903 }
Julia Reynolds3d9eb782014-08-11 16:40:08 -04004904 } else if (UserManager.ENSURE_VERIFY_APPS.equals(key)) {
4905 Settings.Global.putStringForUser(mContext.getContentResolver(),
4906 Settings.Global.PACKAGE_VERIFIER_ENABLE, "1",
Amith Yamasani8cd28b52014-06-08 17:54:27 -07004907 userHandle);
Julia Reynolds3d9eb782014-08-11 16:40:08 -04004908 Settings.Global.putStringForUser(mContext.getContentResolver(),
4909 Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, "1",
Amith Yamasani8cd28b52014-06-08 17:54:27 -07004910 userHandle);
Julia Reynolds3d9eb782014-08-11 16:40:08 -04004911 } else if (UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES.equals(key)) {
4912 Settings.Secure.putIntForUser(mContext.getContentResolver(),
4913 Settings.Secure.INSTALL_NON_MARKET_APPS, 0,
Amith Yamasani8cd28b52014-06-08 17:54:27 -07004914 userHandle);
Julia Reynolds3d9eb782014-08-11 16:40:08 -04004915 }
4916 }
Amith Yamasani8cd28b52014-06-08 17:54:27 -07004917 mUserManager.setUserRestriction(key, enabled, user);
Zoltan Szatmary-Ban871fa732015-01-16 12:36:29 +00004918 if (enabled != alreadyRestricted) {
4919 if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) {
4920 // Send out notifications however as some clients may want to reread the
4921 // value which actually changed due to a restriction having been applied.
4922 final String property = Settings.Secure.SYS_PROP_SETTING_VERSION;
4923 long version = SystemProperties.getLong(property, 0) + 1;
4924 SystemProperties.set(property, Long.toString(version));
4925
4926 final String name = Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
4927 Uri url = Uri.withAppendedPath(Settings.Secure.CONTENT_URI, name);
4928 mContext.getContentResolver().notifyChange(url, null, true, userHandle);
4929 }
4930 }
Amith Yamasanibe465322014-04-24 13:45:17 -07004931 } finally {
4932 restoreCallingIdentity(id);
4933 }
Julia Reynoldsb53453f2014-08-22 11:42:43 -04004934 if (!enabled && alreadyRestricted) {
4935 try {
4936 if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) {
4937 iAudioService.setMicrophoneMute(false, who.getPackageName());
4938 } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) {
4939 iAudioService.setMasterMute(false, 0, who.getPackageName(), null);
4940 }
4941 } catch (RemoteException re) {
4942 Slog.e(LOG_TAG, "Failed to talk to AudioService.", re);
4943 }
4944 }
Benjamin Franz05720542014-10-15 17:39:13 +01004945 sendChangedNotification(userHandle);
Amith Yamasanibe465322014-04-24 13:45:17 -07004946 }
4947 }
Adam Connors010cfd42014-04-16 12:48:13 +01004948
4949 @Override
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004950 public boolean setApplicationHidden(ComponentName who, String packageName,
4951 boolean hidden) {
Julia Reynolds966881e2014-05-14 12:23:08 -04004952 int callingUserId = UserHandle.getCallingUserId();
4953 synchronized (this) {
4954 if (who == null) {
4955 throw new NullPointerException("ComponentName is null");
4956 }
4957 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
4958
4959 long id = Binder.clearCallingIdentity();
4960 try {
4961 IPackageManager pm = AppGlobals.getPackageManager();
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004962 return pm.setApplicationHiddenSettingAsUser(packageName, hidden, callingUserId);
Julia Reynolds966881e2014-05-14 12:23:08 -04004963 } catch (RemoteException re) {
4964 // shouldn't happen
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004965 Slog.e(LOG_TAG, "Failed to setApplicationHiddenSetting", re);
Julia Reynolds966881e2014-05-14 12:23:08 -04004966 } finally {
4967 restoreCallingIdentity(id);
4968 }
4969 return false;
4970 }
4971 }
4972
4973 @Override
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004974 public boolean isApplicationHidden(ComponentName who, String packageName) {
Julia Reynolds966881e2014-05-14 12:23:08 -04004975 int callingUserId = UserHandle.getCallingUserId();
4976 synchronized (this) {
4977 if (who == null) {
4978 throw new NullPointerException("ComponentName is null");
4979 }
4980 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
4981
4982 long id = Binder.clearCallingIdentity();
4983 try {
4984 IPackageManager pm = AppGlobals.getPackageManager();
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004985 return pm.getApplicationHiddenSettingAsUser(packageName, callingUserId);
Julia Reynolds966881e2014-05-14 12:23:08 -04004986 } catch (RemoteException re) {
4987 // shouldn't happen
Amith Yamasanie5bcff62014-07-19 15:44:09 -07004988 Slog.e(LOG_TAG, "Failed to getApplicationHiddenSettingAsUser", re);
Julia Reynolds966881e2014-05-14 12:23:08 -04004989 } finally {
4990 restoreCallingIdentity(id);
4991 }
4992 return false;
4993 }
4994 }
4995
4996 @Override
Adam Connors655be2a2014-07-14 09:01:25 +00004997 public void enableSystemApp(ComponentName who, String packageName) {
4998 synchronized (this) {
4999 if (who == null) {
5000 throw new NullPointerException("ComponentName is null");
5001 }
5002
5003 // This API can only be called by an active device admin,
5004 // so try to retrieve it to check that the caller is one.
5005 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
5006
5007 int userId = UserHandle.getCallingUserId();
5008 long id = Binder.clearCallingIdentity();
5009
5010 try {
Adam Connors655be2a2014-07-14 09:01:25 +00005011 if (DBG) {
5012 Slog.v(LOG_TAG, "installing " + packageName + " for "
5013 + userId);
5014 }
5015
Jessica Hummeldd31a102014-09-16 11:56:50 +01005016 UserManager um = UserManager.get(mContext);
5017 UserInfo primaryUser = um.getProfileParent(userId);
5018
5019 // Call did not come from a managed profile
5020 if (primaryUser == null) {
5021 primaryUser = um.getUserInfo(userId);
5022 }
5023
Adam Connors655be2a2014-07-14 09:01:25 +00005024 IPackageManager pm = AppGlobals.getPackageManager();
5025 if (!isSystemApp(pm, packageName, primaryUser.id)) {
5026 throw new IllegalArgumentException("Only system apps can be enabled this way.");
5027 }
5028
5029 // Install the app.
5030 pm.installExistingPackageAsUser(packageName, userId);
5031
5032 } catch (RemoteException re) {
5033 // shouldn't happen
5034 Slog.wtf(LOG_TAG, "Failed to install " + packageName, re);
5035 } finally {
5036 restoreCallingIdentity(id);
5037 }
5038 }
5039 }
5040
5041 @Override
5042 public int enableSystemAppWithIntent(ComponentName who, Intent intent) {
5043 synchronized (this) {
5044 if (who == null) {
5045 throw new NullPointerException("ComponentName is null");
5046 }
5047
5048 // This API can only be called by an active device admin,
5049 // so try to retrieve it to check that the caller is one.
5050 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
5051
5052 int userId = UserHandle.getCallingUserId();
5053 long id = Binder.clearCallingIdentity();
5054
5055 try {
5056 UserManager um = UserManager.get(mContext);
Adam Connors655be2a2014-07-14 09:01:25 +00005057 UserInfo primaryUser = um.getProfileParent(userId);
5058
Jessica Hummeldd31a102014-09-16 11:56:50 +01005059 // Call did not come from a managed profile.
5060 if (primaryUser == null) {
5061 primaryUser = um.getUserInfo(userId);
5062 }
5063
Adam Connors655be2a2014-07-14 09:01:25 +00005064 IPackageManager pm = AppGlobals.getPackageManager();
5065 List<ResolveInfo> activitiesToEnable = pm.queryIntentActivities(intent,
5066 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
5067 0, // no flags
5068 primaryUser.id);
5069
5070 if (DBG) Slog.d(LOG_TAG, "Enabling system activities: " + activitiesToEnable);
5071 int numberOfAppsInstalled = 0;
5072 if (activitiesToEnable != null) {
5073 for (ResolveInfo info : activitiesToEnable) {
5074 if (info.activityInfo != null) {
5075
5076 if (!isSystemApp(pm, info.activityInfo.packageName, primaryUser.id)) {
5077 throw new IllegalArgumentException(
5078 "Only system apps can be enabled this way.");
5079 }
5080
5081
5082 numberOfAppsInstalled++;
5083 pm.installExistingPackageAsUser(info.activityInfo.packageName, userId);
5084 }
5085 }
5086 }
5087 return numberOfAppsInstalled;
5088 } catch (RemoteException e) {
5089 // shouldn't happen
5090 Slog.wtf(LOG_TAG, "Failed to resolve intent for: " + intent);
5091 return 0;
5092 } finally {
5093 restoreCallingIdentity(id);
5094 }
5095 }
5096 }
5097
5098 private boolean isSystemApp(IPackageManager pm, String packageName, int userId)
5099 throws RemoteException {
Jessica Hummeldd31a102014-09-16 11:56:50 +01005100 ApplicationInfo appInfo = pm.getApplicationInfo(packageName, GET_UNINSTALLED_PACKAGES,
5101 userId);
Adam Connors655be2a2014-07-14 09:01:25 +00005102 return (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0;
5103 }
5104
5105 @Override
Sander Alewijnse5c02db62014-05-07 10:46:57 +01005106 public void setAccountManagementDisabled(ComponentName who, String accountType,
5107 boolean disabled) {
5108 if (!mHasFeature) {
5109 return;
5110 }
5111 synchronized (this) {
5112 if (who == null) {
5113 throw new NullPointerException("ComponentName is null");
5114 }
5115 ActiveAdmin ap = getActiveAdminForCallerLocked(who,
5116 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
5117 if (disabled) {
5118 ap.accountTypesWithManagementDisabled.add(accountType);
5119 } else {
5120 ap.accountTypesWithManagementDisabled.remove(accountType);
5121 }
5122 saveSettingsLocked(UserHandle.getCallingUserId());
5123 }
5124 }
5125
5126 @Override
5127 public String[] getAccountTypesWithManagementDisabled() {
Alexandra Gherghina999d3942014-07-03 11:40:08 +01005128 return getAccountTypesWithManagementDisabledAsUser(UserHandle.getCallingUserId());
5129 }
5130
5131 @Override
5132 public String[] getAccountTypesWithManagementDisabledAsUser(int userId) {
5133 enforceCrossUserPermission(userId);
Sander Alewijnse5c02db62014-05-07 10:46:57 +01005134 if (!mHasFeature) {
5135 return null;
5136 }
5137 synchronized (this) {
Alexandra Gherghina999d3942014-07-03 11:40:08 +01005138 DevicePolicyData policy = getUserData(userId);
Sander Alewijnse5c02db62014-05-07 10:46:57 +01005139 final int N = policy.mAdminList.size();
5140 HashSet<String> resultSet = new HashSet<String>();
5141 for (int i = 0; i < N; i++) {
5142 ActiveAdmin admin = policy.mAdminList.get(i);
5143 resultSet.addAll(admin.accountTypesWithManagementDisabled);
5144 }
5145 return resultSet.toArray(new String[resultSet.size()]);
5146 }
5147 }
justinzhang511e0d82014-03-24 16:09:24 -04005148
Kenny Guyc13053b2014-05-29 14:17:17 +01005149 @Override
Esteban Talaverad5c5c132014-08-20 11:35:57 +01005150 public void setUninstallBlocked(ComponentName who, String packageName,
5151 boolean uninstallBlocked) {
Kenny Guyc13053b2014-05-29 14:17:17 +01005152 final int userId = UserHandle.getCallingUserId();
5153
5154 synchronized (this) {
5155 if (who == null) {
5156 throw new NullPointerException("ComponentName is null");
5157 }
5158 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
5159
5160 long id = Binder.clearCallingIdentity();
5161 try {
5162 IPackageManager pm = AppGlobals.getPackageManager();
Esteban Talaverad5c5c132014-08-20 11:35:57 +01005163 pm.setBlockUninstallForUser(packageName, uninstallBlocked, userId);
Kenny Guyc13053b2014-05-29 14:17:17 +01005164 } catch (RemoteException re) {
5165 // Shouldn't happen.
5166 Slog.e(LOG_TAG, "Failed to setBlockUninstallForUser", re);
5167 } finally {
5168 restoreCallingIdentity(id);
5169 }
5170 }
5171 }
5172
5173 @Override
Esteban Talavera729b2a62014-08-27 18:01:58 +01005174 public boolean isUninstallBlocked(ComponentName who, String packageName) {
Rubin Xua97855b2014-11-07 05:41:00 +00005175 // This function should return true if and only if the package is blocked by
5176 // setUninstallBlocked(). It should still return false for other cases of blocks, such as
5177 // when the package is a system app, or when it is an active device admin.
Kenny Guyc13053b2014-05-29 14:17:17 +01005178 final int userId = UserHandle.getCallingUserId();
5179
5180 synchronized (this) {
Rubin Xua97855b2014-11-07 05:41:00 +00005181 if (who != null) {
5182 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
Kenny Guyc13053b2014-05-29 14:17:17 +01005183 }
Kenny Guyc13053b2014-05-29 14:17:17 +01005184
5185 long id = Binder.clearCallingIdentity();
5186 try {
5187 IPackageManager pm = AppGlobals.getPackageManager();
5188 return pm.getBlockUninstallForUser(packageName, userId);
5189 } catch (RemoteException re) {
5190 // Shouldn't happen.
5191 Slog.e(LOG_TAG, "Failed to getBlockUninstallForUser", re);
5192 } finally {
5193 restoreCallingIdentity(id);
5194 }
5195 }
5196 return false;
5197 }
5198
Adam Connors210fe212014-07-17 15:41:43 +01005199 @Override
5200 public void setCrossProfileCallerIdDisabled(ComponentName who, boolean disabled) {
5201 if (!mHasFeature) {
5202 return;
5203 }
5204 synchronized (this) {
5205 if (who == null) {
5206 throw new NullPointerException("ComponentName is null");
5207 }
5208 ActiveAdmin admin = getActiveAdminForCallerLocked(who,
5209 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
5210 if (admin.disableCallerId != disabled) {
5211 admin.disableCallerId = disabled;
5212 saveSettingsLocked(UserHandle.getCallingUserId());
5213 }
5214 }
5215 }
5216
5217 @Override
5218 public boolean getCrossProfileCallerIdDisabled(ComponentName who) {
5219 if (!mHasFeature) {
5220 return false;
5221 }
5222
5223 synchronized (this) {
5224 if (who == null) {
5225 throw new NullPointerException("ComponentName is null");
5226 }
5227
5228 ActiveAdmin admin = getActiveAdminForCallerLocked(who,
5229 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
5230 return admin.disableCallerId;
5231 }
5232 }
5233
5234 @Override
5235 public boolean getCrossProfileCallerIdDisabledForUser(int userId) {
Amith Yamasanieee50942014-07-21 17:04:44 -07005236 // TODO: Should there be a check to make sure this relationship is within a profile group?
5237 //enforceSystemProcess("getCrossProfileCallerIdDisabled can only be called by system");
Adam Connors210fe212014-07-17 15:41:43 +01005238 synchronized (this) {
5239 ActiveAdmin admin = getProfileOwnerAdmin(userId);
5240 return (admin != null) ? admin.disableCallerId : false;
5241 }
5242 }
5243
justinzhang511e0d82014-03-24 16:09:24 -04005244 /**
Jason Monkd7b86212014-06-16 13:15:38 -04005245 * Sets which packages may enter lock task mode.
justinzhang511e0d82014-03-24 16:09:24 -04005246 *
Jason Monkc5185f22014-06-24 11:12:42 -04005247 * This function can only be called by the device owner.
justinzhang511e0d82014-03-24 16:09:24 -04005248 * @param components The list of components allowed to enter lock task mode.
5249 */
Jason Monk48aacba2014-08-13 16:29:08 -04005250 public void setLockTaskPackages(ComponentName who, String[] packages) throws SecurityException {
Jason Monkd7b86212014-06-16 13:15:38 -04005251 synchronized (this) {
Jason Monk48aacba2014-08-13 16:29:08 -04005252 if (who == null) {
5253 throw new NullPointerException("ComponentName is null");
5254 }
5255 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
justinzhang511e0d82014-03-24 16:09:24 -04005256
Jason Monk48aacba2014-08-13 16:29:08 -04005257 int userHandle = Binder.getCallingUserHandle().getIdentifier();
5258 DevicePolicyData policy = getUserData(userHandle);
5259 policy.mLockTaskPackages.clear();
5260 if (packages != null) {
5261 for (int j = 0; j < packages.length; j++) {
5262 String pkg = packages[j];
5263 policy.mLockTaskPackages.add(pkg);
Jason Monkd7b86212014-06-16 13:15:38 -04005264 }
justinzhang511e0d82014-03-24 16:09:24 -04005265 }
Jason Monk48aacba2014-08-13 16:29:08 -04005266
5267 // Store the settings persistently.
5268 saveSettingsLocked(userHandle);
justinzhang511e0d82014-03-24 16:09:24 -04005269 }
justinzhang511e0d82014-03-24 16:09:24 -04005270 }
5271
5272 /**
5273 * This function returns the list of components allowed to start the task lock mode.
5274 */
Jason Monk48aacba2014-08-13 16:29:08 -04005275 public String[] getLockTaskPackages(ComponentName who) {
Jason Monkd7b86212014-06-16 13:15:38 -04005276 synchronized (this) {
Jason Monk48aacba2014-08-13 16:29:08 -04005277 if (who == null) {
5278 throw new NullPointerException("ComponentName is null");
5279 }
5280 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
5281
5282 int userHandle = Binder.getCallingUserHandle().getIdentifier();
Jason Monkd7b86212014-06-16 13:15:38 -04005283 DevicePolicyData policy = getUserData(userHandle);
5284 return policy.mLockTaskPackages.toArray(new String[0]);
5285 }
justinzhang511e0d82014-03-24 16:09:24 -04005286 }
5287
5288 /**
Jason Monkd7b86212014-06-16 13:15:38 -04005289 * This function lets the caller know whether the given package is allowed to start the
justinzhang511e0d82014-03-24 16:09:24 -04005290 * lock task mode.
Jason Monkd7b86212014-06-16 13:15:38 -04005291 * @param pkg The package to check
justinzhang511e0d82014-03-24 16:09:24 -04005292 */
Jason Monkd7b86212014-06-16 13:15:38 -04005293 public boolean isLockTaskPermitted(String pkg) {
justinzhang511e0d82014-03-24 16:09:24 -04005294 // Get current user's devicepolicy
5295 int uid = Binder.getCallingUid();
5296 int userHandle = UserHandle.getUserId(uid);
5297 DevicePolicyData policy = getUserData(userHandle);
Jason Monkd7b86212014-06-16 13:15:38 -04005298 synchronized (this) {
5299 for (int i = 0; i < policy.mLockTaskPackages.size(); i++) {
5300 String lockTaskPackage = policy.mLockTaskPackages.get(i);
justinzhang511e0d82014-03-24 16:09:24 -04005301
Jason Monkd7b86212014-06-16 13:15:38 -04005302 // If the given package equals one of the packages stored our list,
5303 // we allow this package to start lock task mode.
5304 if (lockTaskPackage.equals(pkg)) {
5305 return true;
5306 }
justinzhang511e0d82014-03-24 16:09:24 -04005307 }
5308 }
5309 return false;
5310 }
Julia Reynoldsda551652014-05-14 17:15:16 -04005311
5312 @Override
Jason Monk35c62a42014-06-17 10:24:47 -04005313 public void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userHandle) {
5314 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
5315 throw new SecurityException("notifyLockTaskModeChanged can only be called by system");
5316 }
5317 synchronized (this) {
5318 final DevicePolicyData policy = getUserData(userHandle);
5319 Bundle adminExtras = new Bundle();
Jason Monk35c62a42014-06-17 10:24:47 -04005320 adminExtras.putString(DeviceAdminReceiver.EXTRA_LOCK_TASK_PACKAGE, pkg);
5321 for (ActiveAdmin admin : policy.mAdminList) {
5322 boolean ownsDevice = isDeviceOwner(admin.info.getPackageName());
5323 boolean ownsProfile = (getProfileOwner(userHandle) != null
5324 && getProfileOwner(userHandle).equals(admin.info.getPackageName()));
5325 if (ownsDevice || ownsProfile) {
Jason Monk48aacba2014-08-13 16:29:08 -04005326 if (isEnabled) {
5327 sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_LOCK_TASK_ENTERING,
5328 adminExtras, null);
5329 } else {
5330 sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_LOCK_TASK_EXITING);
5331 }
Jason Monk35c62a42014-06-17 10:24:47 -04005332 }
5333 }
5334 }
5335 }
5336
5337 @Override
Julia Reynoldsda551652014-05-14 17:15:16 -04005338 public void setGlobalSetting(ComponentName who, String setting, String value) {
5339 final ContentResolver contentResolver = mContext.getContentResolver();
5340
5341 synchronized (this) {
5342 if (who == null) {
5343 throw new NullPointerException("ComponentName is null");
5344 }
5345 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
5346
Julia Reynolds9ed66da2014-08-26 15:42:03 -04005347 if (!GLOBAL_SETTINGS_WHITELIST.contains(setting)) {
5348 throw new SecurityException(String.format(
5349 "Permission denial: device owners cannot update %1$s", setting));
5350 }
5351
Julia Reynoldsda551652014-05-14 17:15:16 -04005352 long id = Binder.clearCallingIdentity();
5353 try {
5354 Settings.Global.putString(contentResolver, setting, value);
5355 } finally {
5356 restoreCallingIdentity(id);
5357 }
5358 }
5359 }
5360
5361 @Override
5362 public void setSecureSetting(ComponentName who, String setting, String value) {
5363 int callingUserId = UserHandle.getCallingUserId();
5364 final ContentResolver contentResolver = mContext.getContentResolver();
5365
5366 synchronized (this) {
5367 if (who == null) {
5368 throw new NullPointerException("ComponentName is null");
5369 }
Julia Reynolds82735bc2014-09-04 16:43:30 -04005370 ActiveAdmin activeAdmin =
5371 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
Julia Reynoldsda551652014-05-14 17:15:16 -04005372
Julia Reynolds82735bc2014-09-04 16:43:30 -04005373 if (isDeviceOwner(activeAdmin.info.getPackageName())) {
5374 if (!SECURE_SETTINGS_DEVICEOWNER_WHITELIST.contains(setting)) {
5375 throw new SecurityException(String.format(
5376 "Permission denial: Device owners cannot update %1$s", setting));
5377 }
5378 } else if (!SECURE_SETTINGS_WHITELIST.contains(setting)) {
Julia Reynolds9ed66da2014-08-26 15:42:03 -04005379 throw new SecurityException(String.format(
Julia Reynolds82735bc2014-09-04 16:43:30 -04005380 "Permission denial: Profile owners cannot update %1$s", setting));
Julia Reynolds9ed66da2014-08-26 15:42:03 -04005381 }
5382
Julia Reynoldsda551652014-05-14 17:15:16 -04005383 long id = Binder.clearCallingIdentity();
5384 try {
5385 Settings.Secure.putStringForUser(contentResolver, setting, value, callingUserId);
5386 } finally {
5387 restoreCallingIdentity(id);
5388 }
5389 }
5390 }
Julia Reynolds4a21b252014-06-04 11:11:43 -04005391
5392 @Override
5393 public void setMasterVolumeMuted(ComponentName who, boolean on) {
5394 final ContentResolver contentResolver = mContext.getContentResolver();
5395
5396 synchronized (this) {
5397 if (who == null) {
5398 throw new NullPointerException("ComponentName is null");
5399 }
5400 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
5401
5402 IAudioService iAudioService = IAudioService.Stub.asInterface(
5403 ServiceManager.getService(Context.AUDIO_SERVICE));
5404 try{
5405 iAudioService.setMasterMute(on, 0, who.getPackageName(), null);
5406 } catch (RemoteException re) {
5407 Slog.e(LOG_TAG, "Failed to setMasterMute", re);
5408 }
5409 }
5410 }
5411
5412 @Override
5413 public boolean isMasterVolumeMuted(ComponentName who) {
5414 final ContentResolver contentResolver = mContext.getContentResolver();
5415
5416 synchronized (this) {
5417 if (who == null) {
5418 throw new NullPointerException("ComponentName is null");
5419 }
5420 getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
5421
5422 AudioManager audioManager =
5423 (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
5424 return audioManager.isMasterMute();
5425 }
5426 }
Amith Yamasanied239cb2014-07-16 17:26:17 -07005427
5428 /**
5429 * We need to update the internal state of whether a user has completed setup once. After
5430 * that, we ignore any changes that reset the Settings.Secure.USER_SETUP_COMPLETE changes
5431 * as we don't trust any apps that might try to reset it.
5432 * <p>
5433 * Unfortunately, we don't know which user's setup state was changed, so we write all of
5434 * them.
5435 */
5436 void updateUserSetupComplete() {
5437 List<UserInfo> users = mUserManager.getUsers(true);
5438 ContentResolver resolver = mContext.getContentResolver();
5439 final int N = users.size();
5440 for (int i = 0; i < N; i++) {
5441 int userHandle = users.get(i).id;
5442 if (Settings.Secure.getIntForUser(resolver, Settings.Secure.USER_SETUP_COMPLETE, 0,
5443 userHandle) != 0) {
5444 DevicePolicyData policy = getUserData(userHandle);
Amith Yamasani0da218b2014-07-25 08:03:00 -07005445 if (!policy.mUserSetupComplete) {
5446 policy.mUserSetupComplete = true;
5447 synchronized (this) {
5448 saveSettingsLocked(userHandle);
5449 }
Amith Yamasanied239cb2014-07-16 17:26:17 -07005450 }
5451 }
5452 }
5453 }
5454
5455 private class SetupContentObserver extends ContentObserver {
5456
5457 private final Uri mUserSetupComplete = Settings.Secure.getUriFor(
5458 Settings.Secure.USER_SETUP_COMPLETE);
5459
5460 public SetupContentObserver(Handler handler) {
5461 super(handler);
5462 }
5463
5464 void register(ContentResolver resolver) {
5465 resolver.registerContentObserver(mUserSetupComplete, false, this, UserHandle.USER_ALL);
5466 }
5467
5468 @Override
5469 public void onChange(boolean selfChange, Uri uri) {
5470 if (mUserSetupComplete.equals(uri)) {
5471 updateUserSetupComplete();
5472 }
5473 }
5474 }
Svetoslav976e8bd2014-07-16 15:12:03 -07005475
5476 private final class LocalService extends DevicePolicyManagerInternal {
Svet Ganov6bd70252014-08-20 09:47:47 -07005477 private List<OnCrossProfileWidgetProvidersChangeListener> mWidgetProviderListeners;
5478
Svetoslav976e8bd2014-07-16 15:12:03 -07005479 @Override
5480 public List<String> getCrossProfileWidgetProviders(int profileId) {
Svet Ganov6bd70252014-08-20 09:47:47 -07005481 synchronized (DevicePolicyManagerService.this) {
Svetoslav28433db2014-10-14 15:53:14 -07005482 if (mDeviceOwner == null) {
5483 return Collections.emptyList();
5484 }
Svet Ganov6bd70252014-08-20 09:47:47 -07005485 ComponentName ownerComponent = mDeviceOwner.getProfileOwnerComponent(profileId);
5486 if (ownerComponent == null) {
5487 return Collections.emptyList();
5488 }
5489
Benjamin Franzfadb2b32015-01-14 18:22:42 +00005490 DevicePolicyData policy = getUserDataUnchecked(profileId);
Svet Ganov6bd70252014-08-20 09:47:47 -07005491 ActiveAdmin admin = policy.mAdminMap.get(ownerComponent);
5492
5493 if (admin == null || admin.crossProfileWidgetProviders == null
5494 || admin.crossProfileWidgetProviders.isEmpty()) {
5495 return Collections.emptyList();
5496 }
5497
5498 return admin.crossProfileWidgetProviders;
Svetoslav976e8bd2014-07-16 15:12:03 -07005499 }
Svet Ganov6bd70252014-08-20 09:47:47 -07005500 }
Svetoslav976e8bd2014-07-16 15:12:03 -07005501
Svet Ganov6bd70252014-08-20 09:47:47 -07005502 @Override
5503 public void addOnCrossProfileWidgetProvidersChangeListener(
5504 OnCrossProfileWidgetProvidersChangeListener listener) {
5505 synchronized (DevicePolicyManagerService.this) {
5506 if (mWidgetProviderListeners == null) {
5507 mWidgetProviderListeners = new ArrayList<>();
5508 }
5509 if (!mWidgetProviderListeners.contains(listener)) {
5510 mWidgetProviderListeners.add(listener);
5511 }
Svetoslav318f91b2014-08-06 19:05:57 -07005512 }
Svet Ganov6bd70252014-08-20 09:47:47 -07005513 }
Svetoslav318f91b2014-08-06 19:05:57 -07005514
Svet Ganov6bd70252014-08-20 09:47:47 -07005515 private void notifyCrossProfileProvidersChanged(int userId, List<String> packages) {
5516 final List<OnCrossProfileWidgetProvidersChangeListener> listeners;
5517 synchronized (DevicePolicyManagerService.this) {
5518 listeners = new ArrayList<>(mWidgetProviderListeners);
Svetoslav976e8bd2014-07-16 15:12:03 -07005519 }
Svet Ganov6bd70252014-08-20 09:47:47 -07005520 final int listenerCount = listeners.size();
5521 for (int i = 0; i < listenerCount; i++) {
5522 OnCrossProfileWidgetProvidersChangeListener listener = listeners.get(i);
5523 listener.onCrossProfileWidgetProvidersChanged(userId, packages);
5524 }
Svetoslav976e8bd2014-07-16 15:12:03 -07005525 }
5526 }
Dianne Hackbornd6847842010-01-12 18:14:19 -08005527}