Merge "Persistent connection to DO/PO service." into oc-dev

This commit is contained in:
TreeHugger Robot
2017-04-03 20:35:14 +00:00
committed by Android (Google) Code Review
10 changed files with 562 additions and 10 deletions

View File

@ -102,6 +102,7 @@ LOCAL_SRC_FILES += \
core/java/android/app/IUserSwitchObserver.aidl \
core/java/android/app/IWallpaperManager.aidl \
core/java/android/app/IWallpaperManagerCallback.aidl \
core/java/android/app/admin/IDeviceAdminService.aidl \
core/java/android/app/admin/IDevicePolicyManager.aidl \
core/java/android/app/trust/IStrongAuthTracker.aidl \
core/java/android/app/trust/ITrustManager.aidl \

View File

@ -6232,6 +6232,11 @@ package android.app.admin {
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
}
public class DeviceAdminService extends android.app.Service {
ctor public DeviceAdminService();
method public final android.os.IBinder onBind(android.content.Intent);
}
public class DevicePolicyManager {
method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
@ -6398,6 +6403,7 @@ package android.app.admin {
method public void wipeData(int);
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
field public static final java.lang.String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
field public static final java.lang.String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE";
field public static final java.lang.String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
field public static final java.lang.String ACTION_PROVISIONING_SUCCESSFUL = "android.app.action.PROVISIONING_SUCCESSFUL";

View File

@ -6435,6 +6435,11 @@ package android.app.admin {
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
}
public class DeviceAdminService extends android.app.Service {
ctor public DeviceAdminService();
method public final android.os.IBinder onBind(android.content.Intent);
}
public class DevicePolicyManager {
method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
@ -6622,6 +6627,7 @@ package android.app.admin {
field public static final java.lang.String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
field public static final java.lang.String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
field public static final java.lang.String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE";
field public static final java.lang.String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
field public static final java.lang.String ACTION_PROVISIONING_SUCCESSFUL = "android.app.action.PROVISIONING_SUCCESSFUL";

View File

@ -6251,6 +6251,11 @@ package android.app.admin {
field public static final java.lang.String EXTRA_LOCK_TASK_PACKAGE = "android.app.extra.LOCK_TASK_PACKAGE";
}
public class DeviceAdminService extends android.app.Service {
ctor public DeviceAdminService();
method public final android.os.IBinder onBind(android.content.Intent);
}
public class DevicePolicyManager {
method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
method public boolean addCrossProfileWidgetProvider(android.content.ComponentName, java.lang.String);
@ -6426,6 +6431,7 @@ package android.app.admin {
field public static final java.lang.String ACCOUNT_FEATURE_DEVICE_OR_PROFILE_OWNER_DISALLOWED = "android.account.DEVICE_OR_PROFILE_OWNER_DISALLOWED";
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
field public static final java.lang.String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED";
field public static final java.lang.String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE";
field public static final java.lang.String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED";
field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
field public static final java.lang.String ACTION_PROVISIONING_SUCCESSFUL = "android.app.action.PROVISIONING_SUCCESSFUL";

View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app.admin;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.os.IBinder;
/**
* Base class for a service that device owner/profile owners can optionally have.
*
* <p>The system searches for it with an intent filter with the
* {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE} action, and tries to keep a bound
* connection as long as the hosting user is running, so that the device/profile owner is always
* considered to be in the foreground.
*
* <p>Device/profile owners can use
* {@link android.content.pm.PackageManager#setComponentEnabledSetting(ComponentName, int, int)}
* to disable/enable its own service. For example, when a device/profile owner no longer needs
* to be in the foreground, it can (and should) disable its service.
*
* <p>The service must not be exported.
*
* <p>TODO: Describe how the system handles crashes in DO/PO.
*/
public class DeviceAdminService extends Service {
private final IDeviceAdminServiceImpl mImpl;
public DeviceAdminService() {
mImpl = new IDeviceAdminServiceImpl();
}
@Override
public final IBinder onBind(Intent intent) {
return mImpl.asBinder();
}
private class IDeviceAdminServiceImpl extends IDeviceAdminService.Stub {
}
// So far, we have no methods in this class.
}

View File

@ -1514,6 +1514,16 @@ public class DevicePolicyManager {
CODE_SPLIT_SYSTEM_USER_DEVICE_SYSTEM_USER, CODE_ADD_MANAGED_PROFILE_DISALLOWED})
public @interface ProvisioningPreCondition {}
/**
* Service action: Action for a service that device owner and profile owner can optionally
* own. If a device owner or a profile owner has such a service, the system tries to keep
* a bound connection to it, in order to keep their process always running.
* The service must not be exported.
*/
@SdkConstant(SdkConstantType.SERVICE_ACTION)
public static final String ACTION_DEVICE_ADMIN_SERVICE
= "android.app.action.DEVICE_ADMIN_SERVICE";
/**
* Return true if the given administrator component is currently active (enabled) in the system.
*

View File

@ -0,0 +1,23 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app.admin;
/**
* @hide
*/
interface IDeviceAdminService {
}

View File

@ -0,0 +1,168 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.am;
import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.UserHandle;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter;
/**
* Connects to a given service component on a given user.
*
* - Call {@link #connect()} to create a connection.
* - Call {@link #disconnect()} to disconnect. Make sure to disconnect when the user stops.
*
* Add onConnected/onDisconnected callbacks as needed.
*/
public abstract class PersistentConnection<T> {
private final Object mLock = new Object();
private final String mTag;
private final Context mContext;
private final Handler mHandler;
private final int mUserId;
private final ComponentName mComponentName;
@GuardedBy("mLock")
private boolean mStarted;
@GuardedBy("mLock")
private boolean mIsConnected;
@GuardedBy("mLock")
private T mService;
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (mLock) {
Slog.i(mTag, "Connected: " + mComponentName.flattenToShortString()
+ " u" + mUserId);
mIsConnected = true;
mService = asInterface(service);
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
synchronized (mLock) {
Slog.i(mTag, "Disconnected: " + mComponentName.flattenToShortString()
+ " u" + mUserId);
cleanUpConnectionLocked();
}
}
};
public PersistentConnection(@NonNull String tag, @NonNull Context context,
@NonNull Handler handler, int userId, @NonNull ComponentName componentName) {
mTag = tag;
mContext = context;
mHandler = handler;
mUserId = userId;
mComponentName = componentName;
}
public final ComponentName getComponentName() {
return mComponentName;
}
/**
* @return whether connected.
*/
public final boolean isConnected() {
synchronized (mLock) {
return mIsConnected;
}
}
/**
* @return the service binder interface.
*/
public final T getServiceBinder() {
synchronized (mLock) {
return mService;
}
}
/**
* Connects to the service.
*/
public final void connect() {
synchronized (mLock) {
if (mStarted) {
return;
}
mStarted = true;
final Intent service = new Intent().setComponent(mComponentName);
final boolean success = mContext.bindServiceAsUser(service, mServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
mHandler, UserHandle.of(mUserId));
if (!success) {
Slog.e(mTag, "Binding: " + service.getComponent() + " u" + mUserId
+ " failed.");
}
}
}
private void cleanUpConnectionLocked() {
mIsConnected = false;
mService = null;
}
/**
* Disconnect from the service.
*/
public final void disconnect() {
synchronized (mLock) {
if (!mStarted) {
return;
}
Slog.i(mTag, "Stopping: " + mComponentName.flattenToShortString() + " u" + mUserId);
mStarted = false;
mContext.unbindService(mServiceConnection);
cleanUpConnectionLocked();
}
}
/** Must be implemented by a subclass to convert an {@link IBinder} to a stub. */
protected abstract T asInterface(IBinder binder);
public void dump(String prefix, PrintWriter pw) {
synchronized (mLock) {
pw.print(prefix);
pw.print(mComponentName.flattenToShortString());
pw.print(mStarted ? " [started]" : " [not started]");
pw.print(mIsConnected ? " [connected]" : " [not connected]");
pw.println();
}
}
}

View File

@ -0,0 +1,211 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.devicepolicy;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.admin.DevicePolicyManager;
import android.app.admin.IDeviceAdminService;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
import com.android.server.am.PersistentConnection;
import java.io.PrintWriter;
import java.util.List;
/**
* Manages connections to persistent services in owner packages.
*/
public class DeviceAdminServiceController {
static final String TAG = DevicePolicyManagerService.LOG_TAG;
static final boolean DEBUG = false; // DO NOT MERGE WITH TRUE.
final Object mLock = new Object();
final Context mContext;
private final DevicePolicyManagerService mService;
private final DevicePolicyManagerService.Injector mInjector;
private final Handler mHandler; // needed?
static void debug(String format, Object... args) {
if (!DEBUG) {
return;
}
Slog.d(TAG, String.format(format, args));
}
private class DevicePolicyServiceConnection
extends PersistentConnection<IDeviceAdminService> {
public DevicePolicyServiceConnection(int userId, @NonNull ComponentName componentName) {
super(TAG, mContext, mHandler, userId, componentName);
}
@Override
protected IDeviceAdminService asInterface(IBinder binder) {
return IDeviceAdminService.Stub.asInterface(binder);
}
}
/**
* User-ID -> {@link PersistentConnection}.
*/
@GuardedBy("mLock")
private final SparseArray<DevicePolicyServiceConnection> mConnections = new SparseArray<>();
public DeviceAdminServiceController(DevicePolicyManagerService service) {
mService = service;
mInjector = service.mInjector;
mContext = mInjector.mContext;
mHandler = new Handler(BackgroundThread.get().getLooper());
}
/**
* Find a service that handles {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE}
* in a given package.
*/
@Nullable
private ServiceInfo findService(@NonNull String packageName, int userId) {
final Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_ADMIN_SERVICE);
intent.setPackage(packageName);
try {
final ParceledListSlice<ResolveInfo> pls = mInjector.getIPackageManager()
.queryIntentServices(intent, null, /* flags=*/ 0, userId);
if (pls == null) {
return null;
}
final List<ResolveInfo> list = pls.getList();
if (list.size() == 0) {
return null;
}
// Note if multiple services are found, that's an error, even if only one of them
// is exported.
if (list.size() > 1) {
Log.e(TAG, "More than one DeviceAdminService's found in package "
+ packageName
+ ". They'll all be ignored.");
return null;
}
final ServiceInfo si = list.get(0).serviceInfo;
if (si.exported) {
Log.e(TAG, "DeviceAdminService must not be exported: '"
+ si.getComponentName().flattenToShortString()
+ "' will be ignored.");
return null;
}
return si;
} catch (RemoteException e) {
}
return null;
}
/**
* Find a service that handles {@link DevicePolicyManager#ACTION_DEVICE_ADMIN_SERVICE}
* in an owner package and connect to it.
*/
public void startServiceForOwner(@NonNull String packageName, int userId,
@NonNull String actionForLog) {
final long token = mInjector.binderClearCallingIdentity();
try {
synchronized (mLock) {
final ServiceInfo service = findService(packageName, userId);
if (service == null) {
debug("Owner package %s on u%d has no service.",
packageName, userId);
disconnectServiceOnUserLocked(userId, actionForLog);
return;
}
// See if it's already running.
final PersistentConnection<IDeviceAdminService> existing =
mConnections.get(userId);
if (existing != null) {
if (existing.getComponentName().equals(service.getComponentName())) {
return;
}
disconnectServiceOnUserLocked(userId, actionForLog);
}
debug("Owner package %s on u%d has service %s for %s",
packageName, userId,
service.getComponentName().flattenToShortString(), actionForLog);
final DevicePolicyServiceConnection conn =
new DevicePolicyServiceConnection(
userId, service.getComponentName());
mConnections.put(userId, conn);
conn.connect();
}
} finally {
mInjector.binderRestoreCallingIdentity(token);
}
}
/**
* Stop an owner service on a given user.
*/
public void stopServiceForOwner(int userId, @NonNull String actionForLog) {
final long token = mInjector.binderClearCallingIdentity();
try {
synchronized (mLock) {
disconnectServiceOnUserLocked(userId, actionForLog);
}
} finally {
mInjector.binderRestoreCallingIdentity(token);
}
}
private void disconnectServiceOnUserLocked(int userId, @NonNull String actionForLog) {
final DevicePolicyServiceConnection conn = mConnections.get(userId);
if (conn != null) {
debug("Stopping service for u%d if already running for %s.",
userId, actionForLog);
conn.disconnect();
mConnections.remove(userId);
}
}
public void dump(String prefix, PrintWriter pw) {
synchronized (mLock) {
if (mConnections.size() == 0) {
return;
}
pw.println();
pw.print(prefix); pw.println("Owner Services:");
for (int i = 0; i < mConnections.size(); i++) {
final int userId = mConnections.keyAt(i);
pw.print(prefix); pw.print(" "); pw.print("User: "); pw.println(userId);
final DevicePolicyServiceConnection con = mConnections.valueAt(i);
con.dump(prefix + " ", pw);
}
}
}
}

View File

@ -140,7 +140,6 @@ import android.os.storage.StorageManager;
import android.provider.ContactsContract.QuickContact;
import android.provider.ContactsInternal;
import android.provider.Settings;
import android.security.Credentials;
import android.security.IKeyChainAliasCallback;
import android.security.IKeyChainService;
import android.security.KeyChain;
@ -194,7 +193,6 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -365,6 +363,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final UserManagerInternal mUserManagerInternal;
final TelephonyManager mTelephonyManager;
private final LockPatternUtils mLockPatternUtils;
private final DeviceAdminServiceController mDeviceAdminServiceController;
/**
* Contains (package-user) pairs to remove. An entry (p, u) implies that removal of package p
@ -459,7 +458,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public void onStartUser(int userHandle) {
mService.onStartUser(userHandle);
mService.handleStartUser(userHandle);
}
@Override
public void onUnlockUser(int userHandle) {
mService.handleUnlockUser(userHandle);
}
@Override
public void onStopUser(int userHandle) {
mService.handleStopUser(userHandle);
}
}
@ -1420,7 +1429,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
private void handlePackagesChanged(String packageName, int userHandle) {
private void handlePackagesChanged(@Nullable String packageName, int userHandle) {
boolean removedAdmin = false;
if (VERBOSE_LOG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
DevicePolicyData policy = getUserData(userHandle);
@ -1461,6 +1470,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
// If it's an owner package, we may need to refresh the bound connection.
final ComponentName owner = getOwnerComponent(userHandle);
if ((packageName != null) && (owner != null)
&& (owner.getPackageName().equals(packageName))) {
startOwnerService(userHandle, "package-broadcast");
}
// Persist updates if the removed package was an admin or delegate.
if (removedAdmin || removedDelegate) {
saveSettingsLocked(policy.mUserHandle);
@ -1791,6 +1807,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Needed when mHasFeature == false, because it controls the certificate warning text.
mCertificateMonitor = new CertificateMonitor(this, mInjector, mBackgroundHandler);
mDeviceAdminServiceController = new DeviceAdminServiceController(this);
if (!mHasFeature) {
// Skip the rest of the initialization
return;
@ -2943,7 +2961,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
loadOwners();
cleanUpOldUsers();
ensureUnknownSourcesRestrictionForProfileOwners();
onStartUser(UserHandle.USER_SYSTEM);
handleStartUser(UserHandle.USER_SYSTEM);
// Register an observer for watching for user setup complete and settings changes.
mSetupContentObserver.register();
@ -2990,10 +3008,32 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
private void onStartUser(int userId) {
void handleStartUser(int userId) {
updateScreenCaptureDisabledInWindowManager(userId,
getScreenCaptureDisabled(null, userId));
pushUserRestrictions(userId);
startOwnerService(userId, "start-user");
}
void handleUnlockUser(int userId) {
startOwnerService(userId, "unlock-user");
}
void handleStopUser(int userId) {
stopOwnerService(userId, "stop-user");
}
private void startOwnerService(int userId, String actionForLog) {
final ComponentName owner = getOwnerComponent(userId);
if (owner != null) {
mDeviceAdminServiceController.startServiceForOwner(
owner.getPackageName(), userId, actionForLog);
}
}
private void stopOwnerService(int userId, String actionForLog) {
mDeviceAdminServiceController.stopServiceForOwner(userId, actionForLog);
}
private void cleanUpOldUsers() {
@ -5078,7 +5118,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* @param callerPackage the name of the calling package. Required if {@code who} is
* {@code null}.
* @param reqPolicy the policy used in the API whose access permission is being checked.
* @param scoppe the delegation scope corresponding to the API being checked.
* @param scope the delegation scope corresponding to the API being checked.
* @throws SecurityException if {@code who} is given and is not an owner for {@code reqPolicy};
* or when {@code who} is {@code null} and {@code callerPackage} is not a delegate
* of {@code scope}.
@ -6460,6 +6500,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
mDeviceAdminServiceController.startServiceForOwner(
admin.getPackageName(), userId, "set-device-owner");
Slog.i(LOG_TAG, "Device owner set: " + admin + " on user " + userId);
return true;
}
@ -6615,6 +6658,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
private void clearDeviceOwnerLocked(ActiveAdmin admin, int userId) {
mDeviceAdminServiceController.stopServiceForOwner(userId, "clear-device-owner");
if (admin != null) {
admin.disableCamera = false;
admin.userRestrictions = null;
@ -6692,6 +6737,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} finally {
mInjector.binderRestoreCallingIdentity(id);
}
mDeviceAdminServiceController.startServiceForOwner(
who.getPackageName(), userHandle, "set-profile-owner");
return true;
}
}
@ -6723,6 +6770,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
public void clearProfileOwnerLocked(ActiveAdmin admin, int userId) {
mDeviceAdminServiceController.stopServiceForOwner(userId, "clear-profile-owner");
if (admin != null) {
admin.disableCamera = false;
admin.userRestrictions = null;
@ -7275,6 +7324,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (this) {
pw.println("Current Device Policy Manager state:");
mOwners.dump(" ", pw);
mDeviceAdminServiceController.dump(" ", pw);
int userCount = mUserData.size();
for (int u = 0; u < userCount; u++) {
DevicePolicyData policy = getUserData(mUserData.keyAt(u));
@ -9624,6 +9674,21 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return null;
}
/**
* Return device owner or profile owner set on a given user.
*/
private @Nullable ComponentName getOwnerComponent(int userId) {
synchronized (this) {
if (mOwners.getDeviceOwnerUserId() == userId) {
return mOwners.getDeviceOwnerComponent();
}
if (mOwners.hasProfileOwner(userId)) {
return mOwners.getProfileOwnerComponent(userId);
}
}
return null;
}
private int checkManagedUserProvisioningPreCondition(int callingUserId) {
if (!hasFeatureManagedUsers()) {
return CODE_MANAGED_USERS_NOT_SUPPORTED;