Merge "Persistent connection to DO/PO service." into oc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
dcc792a13f
@ -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 \
|
||||
|
@ -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";
|
||||
|
@ -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";
|
||||
|
@ -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";
|
||||
|
56
core/java/android/app/admin/DeviceAdminService.java
Normal file
56
core/java/android/app/admin/DeviceAdminService.java
Normal 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.
|
||||
}
|
@ -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.
|
||||
*
|
||||
|
23
core/java/android/app/admin/IDeviceAdminService.aidl
Normal file
23
core/java/android/app/admin/IDeviceAdminService.aidl
Normal 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 {
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
@ -1434,9 +1443,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|
||||
if (packageName == null || packageName.equals(adminPackage)) {
|
||||
if (mIPackageManager.getPackageInfo(adminPackage, 0, userHandle) == null
|
||||
|| mIPackageManager.getReceiverInfo(aa.info.getComponent(),
|
||||
PackageManager.MATCH_DIRECT_BOOT_AWARE
|
||||
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
|
||||
userHandle) == null) {
|
||||
PackageManager.MATCH_DIRECT_BOOT_AWARE
|
||||
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
|
||||
userHandle) == null) {
|
||||
removedAdmin = true;
|
||||
policy.mAdminList.remove(i);
|
||||
policy.mAdminMap.remove(aa.info.getComponent());
|
||||
@ -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;
|
||||
|
Reference in New Issue
Block a user