Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70d24a0b authored by Makoto Onuki's avatar Makoto Onuki Committed by Android (Google) Code Review
Browse files

Merge "Fix deadlock regarding screen-capture-disabled" into pi-dev

parents a46e4d10 04ef4476
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
/*
 * 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;
        }
    }
}
+6 −0
Original line number Diff line number Diff line
@@ -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();
}
+3 −2
Original line number Diff line number Diff line
@@ -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.
    /**
+2 −3
Original line number Diff line number Diff line
@@ -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
+9 −35
Original line number Diff line number Diff line
@@ -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));
        }
    }

Loading