Merge "Fix deadlock regarding screen-capture-disabled" into pi-dev
This commit is contained in:
57
core/java/android/app/admin/DevicePolicyCache.java
Normal file
57
core/java/android/app/admin/DevicePolicyCache.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.annotation.UserIdInt;
|
||||
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
/**
|
||||
* Stores a copy of the set of device policies maintained by {@link DevicePolicyManager} that
|
||||
* can be accessed from any place without risking dead locks.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public abstract class DevicePolicyCache {
|
||||
protected DevicePolicyCache() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the instance.
|
||||
*/
|
||||
public static DevicePolicyCache getInstance() {
|
||||
final DevicePolicyManagerInternal dpmi =
|
||||
LocalServices.getService(DevicePolicyManagerInternal.class);
|
||||
return (dpmi != null) ? dpmi.getDevicePolicyCache() : EmptyDevicePolicyCache.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link DevicePolicyManager#getScreenCaptureDisabled}
|
||||
*/
|
||||
public abstract boolean getScreenCaptureDisabled(@UserIdInt int userHandle);
|
||||
|
||||
/**
|
||||
* Empty implementation.
|
||||
*/
|
||||
private static class EmptyDevicePolicyCache extends DevicePolicyCache {
|
||||
private static final EmptyDevicePolicyCache INSTANCE = new EmptyDevicePolicyCache();
|
||||
|
||||
@Override
|
||||
public boolean getScreenCaptureDisabled(int userHandle) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,4 +141,10 @@ public abstract class DevicePolicyManagerInternal {
|
||||
* @return localized error message
|
||||
*/
|
||||
public abstract CharSequence getPrintingDisabledReasonForUser(@UserIdInt int userId);
|
||||
|
||||
/**
|
||||
* @return cached version of DPM policies that can be accessed without risking deadlocks.
|
||||
* Do not call it directly. Use {@link DevicePolicyCache#getInstance()} instead.
|
||||
*/
|
||||
protected abstract DevicePolicyCache getDevicePolicyCache();
|
||||
}
|
||||
|
||||
@@ -181,9 +181,10 @@ interface IWindowManager
|
||||
void setStrictModeVisualIndicatorPreference(String enabled);
|
||||
|
||||
/**
|
||||
* Set whether screen capture is disabled for all windows of a specific user
|
||||
* Set whether screen capture is disabled for all windows of a specific user from
|
||||
* the device policy cache.
|
||||
*/
|
||||
void setScreenCaptureDisabled(int userId, boolean disabled);
|
||||
void refreshScreenCaptureDisabled(int userId);
|
||||
|
||||
// These can only be called with the SET_ORIENTATION permission.
|
||||
/**
|
||||
|
||||
@@ -256,6 +256,7 @@ import android.app.RemoteAction;
|
||||
import android.app.WaitResult;
|
||||
import android.app.WindowConfiguration.ActivityType;
|
||||
import android.app.WindowConfiguration.WindowingMode;
|
||||
import android.app.admin.DevicePolicyCache;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.assist.AssistContent;
|
||||
import android.app.assist.AssistStructure;
|
||||
@@ -13727,9 +13728,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
userId = activity.userId;
|
||||
}
|
||||
DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
|
||||
Context.DEVICE_POLICY_SERVICE);
|
||||
return (dpm == null) || (!dpm.getScreenCaptureDisabled(null, userId));
|
||||
return !DevicePolicyCache.getInstance().getScreenCaptureDisabled(userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,7 +25,6 @@ import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
|
||||
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
|
||||
import static android.app.StatusBarManager.DISABLE_MASK;
|
||||
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
|
||||
import static android.content.Intent.ACTION_USER_REMOVED;
|
||||
import static android.content.Intent.EXTRA_USER_HANDLE;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.os.Process.SYSTEM_UID;
|
||||
@@ -122,6 +121,7 @@ import android.app.ActivityThread;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.IActivityManager;
|
||||
import android.app.IAssistDataReceiver;
|
||||
import android.app.admin.DevicePolicyCache;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
@@ -380,14 +380,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
case ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED:
|
||||
mKeyguardDisableHandler.sendEmptyMessage(KEYGUARD_POLICY_CHANGED);
|
||||
break;
|
||||
case ACTION_USER_REMOVED:
|
||||
final int userId = intent.getIntExtra(EXTRA_USER_HANDLE, USER_NULL);
|
||||
if (userId != USER_NULL) {
|
||||
synchronized (mWindowMap) {
|
||||
mScreenCaptureDisabled.remove(userId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -519,13 +511,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
/** List of window currently causing non-system overlay windows to be hidden. */
|
||||
private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Stores for each user whether screencapture is disabled
|
||||
* This array is essentially a cache for all userId for
|
||||
* {@link android.app.admin.DevicePolicyManager#getScreenCaptureDisabled}
|
||||
*/
|
||||
private SparseArray<Boolean> mScreenCaptureDisabled = new SparseArray<>();
|
||||
|
||||
IInputMethodManager mInputMethodManager;
|
||||
|
||||
AccessibilityController mAccessibilityController;
|
||||
@@ -1039,8 +1024,6 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
IntentFilter filter = new IntentFilter();
|
||||
// Track changes to DevicePolicyManager state so we can enable/disable keyguard.
|
||||
filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
|
||||
// Listen to user removal broadcasts so that we can remove the user-specific data.
|
||||
filter.addAction(Intent.ACTION_USER_REMOVED);
|
||||
mContext.registerReceiver(mBroadcastReceiver, filter);
|
||||
|
||||
mLatencyTracker = LatencyTracker.getInstance(context);
|
||||
@@ -1572,41 +1555,32 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether screen capture is disabled for all windows of a specific user.
|
||||
*/
|
||||
boolean isScreenCaptureDisabledLocked(int userId) {
|
||||
Boolean disabled = mScreenCaptureDisabled.get(userId);
|
||||
if (disabled == null) {
|
||||
return false;
|
||||
}
|
||||
return disabled;
|
||||
}
|
||||
|
||||
boolean isSecureLocked(WindowState w) {
|
||||
if ((w.mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
|
||||
return true;
|
||||
}
|
||||
if (isScreenCaptureDisabledLocked(UserHandle.getUserId(w.mOwnerUid))) {
|
||||
if (DevicePolicyCache.getInstance().getScreenCaptureDisabled(
|
||||
UserHandle.getUserId(w.mOwnerUid))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set mScreenCaptureDisabled for specific user
|
||||
* Set whether screen capture is disabled for all windows of a specific user from
|
||||
* the device policy cache.
|
||||
*/
|
||||
@Override
|
||||
public void setScreenCaptureDisabled(int userId, boolean disabled) {
|
||||
public void refreshScreenCaptureDisabled(int userId) {
|
||||
int callingUid = Binder.getCallingUid();
|
||||
if (callingUid != SYSTEM_UID) {
|
||||
throw new SecurityException("Only system can call setScreenCaptureDisabled.");
|
||||
throw new SecurityException("Only system can call refreshScreenCaptureDisabled.");
|
||||
}
|
||||
|
||||
synchronized(mWindowMap) {
|
||||
mScreenCaptureDisabled.put(userId, disabled);
|
||||
// Update secure surface for all windows belonging to this user.
|
||||
mRoot.setSecureSurfaceState(userId, disabled);
|
||||
mRoot.setSecureSurfaceState(userId,
|
||||
DevicePolicyCache.getInstance().getScreenCaptureDisabled(userId));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,8 +70,6 @@ public class WindowManagerShellCommand extends ShellCommand {
|
||||
return runDisplayOverscan(pw);
|
||||
case "scaling":
|
||||
return runDisplayScaling(pw);
|
||||
case "screen-capture":
|
||||
return runSetScreenCapture(pw);
|
||||
case "dismiss-keyguard":
|
||||
return runDismissKeyguard(pw);
|
||||
case "tracing":
|
||||
@@ -210,24 +208,6 @@ public class WindowManagerShellCommand extends ShellCommand {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int runSetScreenCapture(PrintWriter pw) throws RemoteException {
|
||||
String userIdStr = getNextArg();
|
||||
String enableStr = getNextArg();
|
||||
int userId;
|
||||
boolean disable;
|
||||
|
||||
try {
|
||||
userId = Integer.parseInt(userIdStr);
|
||||
} catch (NumberFormatException e) {
|
||||
getErrPrintWriter().println("Error: bad number " + e);
|
||||
return -1;
|
||||
}
|
||||
|
||||
disable = !Boolean.parseBoolean(enableStr);
|
||||
mInternal.setScreenCaptureDisabled(userId, disable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int runDismissKeyguard(PrintWriter pw) throws RemoteException {
|
||||
mInterface.dismissKeyguard(null /* callback */, null /* message */);
|
||||
return 0;
|
||||
@@ -265,8 +245,6 @@ public class WindowManagerShellCommand extends ShellCommand {
|
||||
pw.println(" Set overscan area for display.");
|
||||
pw.println(" scaling [off|auto]");
|
||||
pw.println(" Set display scaling mode.");
|
||||
pw.println(" screen-capture [userId] [true|false]");
|
||||
pw.println(" Enable or disable screen capture.");
|
||||
pw.println(" dismiss-keyguard");
|
||||
pw.println(" Dismiss the keyguard, prompting user for auth if necessary.");
|
||||
if (!IS_USER) {
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.app.admin.DevicePolicyCache;
|
||||
import android.util.SparseBooleanArray;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
/**
|
||||
* Implementation of {@link DevicePolicyCache}, to which {@link DevicePolicyManagerService} pushes
|
||||
* policies.
|
||||
*
|
||||
* TODO Move other copies of policies into this class too.
|
||||
*/
|
||||
public class DevicePolicyCacheImpl extends DevicePolicyCache {
|
||||
/**
|
||||
* Lock object. For simplicity we just always use this as the lock. We could use each object
|
||||
* as a lock object to make it more fine-grained, but that'd make copy-paste error-prone.
|
||||
*/
|
||||
private final Object mLock = new Object();
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private final SparseBooleanArray mScreenCaptureDisabled = new SparseBooleanArray();
|
||||
|
||||
public void onUserRemoved(int userHandle) {
|
||||
synchronized (mLock) {
|
||||
mScreenCaptureDisabled.delete(userHandle);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getScreenCaptureDisabled(int userHandle) {
|
||||
synchronized (mLock) {
|
||||
return mScreenCaptureDisabled.get(userHandle);
|
||||
}
|
||||
}
|
||||
|
||||
public void setScreenCaptureDisabled(int userHandle, boolean disabled) {
|
||||
synchronized (mLock) {
|
||||
mScreenCaptureDisabled.put(userHandle, disabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,6 +98,7 @@ import android.app.PendingIntent;
|
||||
import android.app.StatusBarManager;
|
||||
import android.app.admin.DeviceAdminInfo;
|
||||
import android.app.admin.DeviceAdminReceiver;
|
||||
import android.app.admin.DevicePolicyCache;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.app.admin.DevicePolicyManagerInternal;
|
||||
import android.app.admin.NetworkEvent;
|
||||
@@ -436,6 +437,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
private final DeviceAdminServiceController mDeviceAdminServiceController;
|
||||
private final OverlayPackagesProvider mOverlayPackagesProvider;
|
||||
|
||||
private final DevicePolicyCacheImpl mPolicyCache = new DevicePolicyCacheImpl();
|
||||
|
||||
/**
|
||||
* Contains (package-user) pairs to remove. An entry (p, u) implies that removal of package p
|
||||
* is requested for user u.
|
||||
@@ -2176,6 +2179,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
Slog.w(LOG_TAG, "Tried to remove device policy file for user 0! Ignoring.");
|
||||
return;
|
||||
}
|
||||
mPolicyCache.onUserRemoved(userHandle);
|
||||
|
||||
mOwners.removeProfileOwner(userHandle);
|
||||
mOwners.writeProfileOwner(userHandle);
|
||||
|
||||
@@ -2188,7 +2193,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
policyFile.delete();
|
||||
Slog.i(LOG_TAG, "Removed device policy file " + policyFile.getAbsolutePath());
|
||||
}
|
||||
updateScreenCaptureDisabledInWindowManager(userHandle, false /* default value */);
|
||||
}
|
||||
|
||||
void loadOwners() {
|
||||
@@ -3395,7 +3399,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
|
||||
@Override
|
||||
void handleStartUser(int userId) {
|
||||
updateScreenCaptureDisabledInWindowManager(userId,
|
||||
updateScreenCaptureDisabled(userId,
|
||||
getScreenCaptureDisabled(null, userId));
|
||||
pushUserRestrictions(userId);
|
||||
|
||||
@@ -6632,7 +6636,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
if (ap.disableScreenCapture != disabled) {
|
||||
ap.disableScreenCapture = disabled;
|
||||
saveSettingsLocked(userHandle);
|
||||
updateScreenCaptureDisabledInWindowManager(userHandle, disabled);
|
||||
updateScreenCaptureDisabled(userHandle, disabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6664,13 +6668,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void updateScreenCaptureDisabledInWindowManager(final int userHandle,
|
||||
final boolean disabled) {
|
||||
private void updateScreenCaptureDisabled(int userHandle, boolean disabled) {
|
||||
mPolicyCache.setScreenCaptureDisabled(userHandle, disabled);
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
mInjector.getIWindowManager().setScreenCaptureDisabled(userHandle, disabled);
|
||||
mInjector.getIWindowManager().refreshScreenCaptureDisabled(userHandle);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(LOG_TAG, "Unable to notify WindowManager.", e);
|
||||
}
|
||||
@@ -10502,6 +10506,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
.getResources().getString(R.string.printing_disabled_by, appLabel);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DevicePolicyCache getDevicePolicyCache() {
|
||||
return mPolicyCache;
|
||||
}
|
||||
}
|
||||
|
||||
private Intent createShowAdminSupportIntent(ComponentName admin, int userId) {
|
||||
|
||||
Reference in New Issue
Block a user