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

Commit 3bf69d6d authored by seokgyun.hong's avatar seokgyun.hong Committed by BK Choi
Browse files

Prevent calls to StatusBarManagerInternal from visible background users

Visible background users have access to UI on assigned displays on devices that have config_multiuserVisibleBackgroundUsers enabled. The main use case is Automotive's multi-display Whole Cabin experience where
passengers (modeled as visible background users) can interact with the display in front of them concurrently with the driver (modeled as the the current user) interacting with driver's display.

- Calls to StatusBarManagerInternal trigger callbacks to the registered
  IStatusBar for the current user.
- However, StatusBarManagerInternal APIs can be called from not only
  the current user but also visible background users.
- We should prevent this to ensure that visible background users do not interfere with the current user's experience.

Bug: 332222893
Flag: EXEMPT bugfix
Test: atest MagnificationConnectionManagerTest
      atest WmTests:PhoneWindowManagerTests
(cherry picked from https://partner-android-review.googlesource.com/q/commit:62538ec79f939853bd4ea75e81f4f46204fce72d)

Change-Id: Icdc6515e69e8044cf972a9e14e2fdd7f7a4b6958
parent 15ea1c90
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -3653,6 +3653,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
            return;
        }

        // Magnification connection should not be requested for visible background users.
        // (b/332222893)
        if (mUmi.isVisibleBackgroundFullUser(userState.mUserId)) {
            return;
        }

        final boolean shortcutEnabled = (userState.isShortcutMagnificationEnabledLocked()
                || userState.isMagnificationSingleFingerTripleTapEnabledLocked()
                || (Flags.enableMagnificationMultipleFingerMultipleTapGesture()
+10 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.accessibility.magnification;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_MAGNIFICATION_CONNECTION;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_MAGNIFICATION_CONNECTION_CALLBACK;
import static android.os.Build.HW_TIMEOUT_MULTIPLIER;
import static android.os.UserHandle.getCallingUserId;
import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK;

import static com.android.server.accessibility.AccessibilityManagerService.INVALID_SERVICE_ID;
@@ -54,6 +55,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityTraceManager;
import com.android.server.pm.UserManagerInternal;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wm.WindowManagerInternal;

@@ -209,6 +211,7 @@ public class MagnificationConnectionManager implements
    private final Callback mCallback;
    private final AccessibilityTraceManager mTrace;
    private final MagnificationScaleProvider mScaleProvider;
    private final UserManagerInternal mUserManagerInternal;

    public MagnificationConnectionManager(Context context, Object lock, @NonNull Callback callback,
            AccessibilityTraceManager trace, MagnificationScaleProvider scaleProvider) {
@@ -217,6 +220,7 @@ public class MagnificationConnectionManager implements
        mCallback = callback;
        mTrace = trace;
        mScaleProvider = scaleProvider;
        mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
    }

    /**
@@ -280,12 +284,18 @@ public class MagnificationConnectionManager implements
     * Requests {@link IMagnificationConnection} through
     * {@link StatusBarManagerInternal#requestMagnificationConnection(boolean)} and
     * destroys all window magnifications if necessary.
     * NOTE: Currently, this is not allowed to call from visible background users.(b/332222893)
     *
     * @param connect {@code true} if needs connection, otherwise set the connection to null and
     *                destroy all window magnifications.
     * @return {@code true} if {@link IMagnificationConnection} state is going to change.
     */
    public boolean requestConnection(boolean connect) {
        final int callingUserId = getCallingUserId();
        if (mUserManagerInternal.isVisibleBackgroundFullUser(callingUserId)) {
            throw new SecurityException("Visible background user(u" + callingUserId
                    + " is not permitted to request magnification connection.");
        }
        if (DBG) {
            Slog.d(TAG, "requestConnection :" + connect);
        }
+33 −3
Original line number Diff line number Diff line
@@ -734,7 +734,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                    KeyEvent.KEYCODE_ASSIST,
                    KeyEvent.KEYCODE_VOICE_ASSIST,
                    KeyEvent.KEYCODE_MUTE,
                    KeyEvent.KEYCODE_VOLUME_MUTE
                    KeyEvent.KEYCODE_VOLUME_MUTE,
                    KeyEvent.KEYCODE_RECENT_APPS,
                    KeyEvent.KEYCODE_APP_SWITCH,
                    KeyEvent.KEYCODE_NOTIFICATION
            ));

    private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
@@ -2077,12 +2080,21 @@ public class PhoneWindowManager implements WindowManagerPolicy {
            }
            switch (mDoubleTapOnHomeBehavior) {
                case DOUBLE_TAP_HOME_RECENT_SYSTEM_UI:
                    if (!isKeyEventForCurrentUser(
                            event.getDisplayId(), event.getKeyCode(), "toggleRecentApps")) {
                        break;
                    }
                    notifyKeyGestureCompleted(event,
                            KeyGestureEvent.KEY_GESTURE_TYPE_APP_SWITCH);
                    mHomeConsumed = true;
                    toggleRecentApps();
                    break;
                case DOUBLE_TAP_HOME_PIP_MENU:
                    if (!isKeyEventForCurrentUser(
                            event.getDisplayId(), event.getKeyCode(),
                            "showPictureInPictureMenu")) {
                        break;
                    }
                    mHomeConsumed = true;
                    showPictureInPictureMenuInternal();
                    break;
@@ -2111,12 +2123,20 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                    }
                    break;
                case LONG_PRESS_HOME_ASSIST:
                    if (!isKeyEventForCurrentUser(
                            event.getDisplayId(), event.getKeyCode(), "launchAssistAction")) {
                        break;
                    }
                    notifyKeyGestureCompleted(event,
                            KeyGestureEvent.KEY_GESTURE_TYPE_LAUNCH_ASSISTANT);
                    launchAssistAction(null, event.getDeviceId(), event.getEventTime(),
                            AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS);
                    break;
                case LONG_PRESS_HOME_NOTIFICATION_PANEL:
                    if (!isKeyEventForCurrentUser(
                            event.getDisplayId(), event.getKeyCode(), "toggleNotificationPanel")) {
                        break;
                    }
                    notifyKeyGestureCompleted(event,
                            KeyGestureEvent.KEY_GESTURE_TYPE_TOGGLE_NOTIFICATION_PANEL);
                    toggleNotificationPanel();
@@ -3477,7 +3497,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {

        if (isUserSetupComplete() && !keyguardOn) {
            if (mModifierShortcutManager.interceptKey(event)) {
                if (isKeyEventForCurrentUser(
                        event.getDisplayId(), event.getKeyCode(),
                        "dismissKeyboardShortcutsMenu")) {
                    dismissKeyboardShortcutsMenu();
                }
                mPendingMetaAction = false;
                mPendingCapsLockToggle = false;
                return true;
@@ -4733,7 +4757,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        }

        // no keyguard stuff to worry about, just launch home!
        if (mRecentsVisible) {
        // If Recents is visible and the action is not from visible background users,
        // hide Recents and notify it to launch Home.
        if (mRecentsVisible
                && (!mVisibleBackgroundUsersEnabled || displayId == DEFAULT_DISPLAY)) {
            try {
                ActivityManager.getService().stopAppSwitches();
            } catch (RemoteException e) {}
@@ -5477,6 +5504,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
     * Notify the StatusBar that a system key was pressed.
     */
    private void sendSystemKeyToStatusBar(KeyEvent key) {
        if (!isKeyEventForCurrentUser(key.getDisplayId(), key.getKeyCode(), "handleSystemKey")) {
            return;
        }
        IStatusBarService statusBar = getStatusBarService();
        if (statusBar != null) {
            try {
+12 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemService.TargetUser;
import com.android.server.pm.UserManagerInternal;
import com.android.server.statusbar.StatusBarManagerInternal;

import java.io.FileDescriptor;
@@ -89,6 +90,8 @@ public class SearchManagerService extends ISearchManager.Stub {
    @GuardedBy("mSearchables")
    private final SparseArray<Searchables> mSearchables = new SparseArray<>();

    private final UserManagerInternal mUserManagerInternal;

    /**
     * Initializes the Search Manager service in the provided system context.
     * Only one instance of this object should be created!
@@ -101,6 +104,7 @@ public class SearchManagerService extends ISearchManager.Stub {
        mMyPackageMonitor.register(context, null, UserHandle.ALL, true);
        new GlobalSearchProviderObserver(context.getContentResolver());
        mHandler = BackgroundThread.getHandler();
        mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
    }

    private Searchables getSearchables(int userId) {
@@ -336,6 +340,14 @@ public class SearchManagerService extends ISearchManager.Stub {

    @Override
    public void launchAssist(int userHandle, Bundle args) {
        // Currently, visible background users are not allowed to launch assist.(b/332222893)
        // TODO(b/368715893): Consider indirect calls from system service when checking the
        // calling user.
        final int callingUserId = UserHandle.getCallingUserId();
        if (mUserManagerInternal.isVisibleBackgroundFullUser(callingUserId)) {
            throw new SecurityException("Visible background user(u" + callingUserId
                    + ") is not permitted to launch assist.");
        }
        StatusBarManagerInternal statusBarManager =
                LocalServices.getService(StatusBarManagerInternal.class);
        if (statusBarManager != null) {
+7 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ import androidx.test.filters.FlakyTest;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityTraceManager;
import com.android.server.pm.UserManagerInternal;
import com.android.server.statusbar.StatusBarManagerInternal;

import org.junit.Before;
@@ -92,12 +93,16 @@ public class MagnificationConnectionManagerTest {
    private MagnificationConnectionManager.Callback mMockCallback;
    private MockContentResolver mResolver;
    private MagnificationConnectionManager mMagnificationConnectionManager;
    @Mock
    private UserManagerInternal mMockUserManagerInternal;

    @Before
    public void setUp() throws RemoteException {
        MockitoAnnotations.initMocks(this);
        LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
        LocalServices.removeServiceForTest(UserManagerInternal.class);
        LocalServices.addService(StatusBarManagerInternal.class, mMockStatusBarManagerInternal);
        LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal);
        mResolver = new MockContentResolver();
        mMockConnection = new MockMagnificationConnection();
        mMagnificationConnectionManager = new MagnificationConnectionManager(mContext, new Object(),
@@ -110,6 +115,8 @@ public class MagnificationConnectionManagerTest {
        Settings.Secure.putFloatForUser(mResolver,
                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, 2.5f,
                CURRENT_USER_ID);

        when(mMockUserManagerInternal.isVisibleBackgroundFullUser(anyInt())).thenReturn(false);
    }

    private void stubSetConnection(boolean needDelay) {