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

Commit a0b24fab authored by Riley Jones's avatar Riley Jones Committed by Android (Google) Code Review
Browse files

Merge "Fix for FAB targets not matching current user on user switch" into main

parents cba4e86e d3e18b81
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -1050,6 +1050,52 @@ public final class AccessibilityManager {
        }
    }

    /**
     * Registers callback for when user initialization has completed.
     * Does nothing if the same callback is already registered.
     *
     * @param callback The callback to be registered
     * @hide
     */
    public void registerUserInitializationCompleteCallback(
            @NonNull IUserInitializationCompleteCallback callback) {
        IAccessibilityManager service;
        synchronized (mLock) {
            service = getServiceLocked();
            if (service == null) {
                return;
            }
        }
        try {
            service.registerUserInitializationCompleteCallback(callback);
        } catch (RemoteException re) {
            Log.e(LOG_TAG, "Error while registering userInitializationCompleteCallback. ", re);
        }
    }

    /**
     * Unregisters callback for when user initialization has completed.
     *
     * @param callback The callback to be unregistered
     * @hide
     */
    public void unregisterUserInitializationCompleteCallback(
            @NonNull IUserInitializationCompleteCallback callback) {
        IAccessibilityManager service;
        synchronized (mLock) {
            service = getServiceLocked();
            if (service == null) {
                return;
            }
        }
        try {
            service.unregisterUserInitializationCompleteCallback(callback);
        } catch (RemoteException re) {
            Log.e(LOG_TAG,
                    "Error while unregistering userInitializationCompleteCallback. ", re);
        }
    }

    /**
     * Whether the current accessibility request comes from an
     * {@link AccessibilityService} with the {@link AccessibilityServiceInfo#isAccessibilityTool}
+7 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.view.accessibility.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityManagerClient;
import android.view.accessibility.AccessibilityWindowAttributes;
import android.view.accessibility.IMagnificationConnection;
import android.view.accessibility.IUserInitializationCompleteCallback;
import android.view.InputEvent;
import android.view.IWindow;
import android.view.MagnificationSpec;
@@ -192,4 +193,10 @@ interface IAccessibilityManager {

    @EnforcePermission("MANAGE_ACCESSIBILITY")
    Bundle getA11yFeatureToTileMap(int userId);

    @RequiresNoPermission
    void registerUserInitializationCompleteCallback(IUserInitializationCompleteCallback callback);

    @RequiresNoPermission
    void unregisterUserInitializationCompleteCallback(IUserInitializationCompleteCallback callback);
}
+35 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.view.accessibility;

/**
 * A callback for when a new user finishes initializing
 * NOTE: Must remain a oneway interface, as it is called from system_server while holding a lock.
 * oneway allows it to return immediately and not hold the lock for longer than is necessary.
 * @hide
 */

oneway interface IUserInitializationCompleteCallback {

    /**
     * Called when a user initialization completes.
     *
     * @param userId the id of the initialized user
     */
    @RequiresNoPermission
    void onUserInitializationComplete(int userId);
}
+30 −11
Original line number Diff line number Diff line
@@ -21,11 +21,13 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;

import android.content.Context;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.UserHandle;
import android.text.TextUtils;
import android.view.Display;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IUserInitializationCompleteCallback;

import androidx.annotation.MainThread;

@@ -68,6 +70,9 @@ public class AccessibilityFloatingMenuController implements
    private int mBtnMode;
    private String mBtnTargets;
    private boolean mIsKeyguardVisible;
    private boolean mIsUserInInitialization;
    @VisibleForTesting
    Handler mHandler;

    @VisibleForTesting
    final KeyguardUpdateMonitorCallback mKeyguardCallback = new KeyguardUpdateMonitorCallback() {
@@ -86,18 +91,14 @@ public class AccessibilityFloatingMenuController implements
        @Override
        public void onUserSwitching(int userId) {
            destroyFloatingMenu();
        }

        @Override
        public void onUserSwitchComplete(int userId) {
            mContext = mContext.createContextAsUser(UserHandle.of(userId), /* flags= */ 0);
            mBtnMode = mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode();
            mBtnTargets =
                    mAccessibilityButtonTargetsObserver.getCurrentAccessibilityButtonTargets();
            handleFloatingMenuVisibility(mIsKeyguardVisible, mBtnMode, mBtnTargets);
            mIsUserInInitialization = true;
        }
    };

    @VisibleForTesting
    final UserInitializationCompleteCallback mUserInitializationCompleteCallback =
            new UserInitializationCompleteCallback();

    @Inject
    public AccessibilityFloatingMenuController(Context context,
            WindowManager windowManager,
@@ -109,7 +110,8 @@ public class AccessibilityFloatingMenuController implements
            KeyguardUpdateMonitor keyguardUpdateMonitor,
            SecureSettings secureSettings,
            DisplayTracker displayTracker,
            NavigationModeController navigationModeController) {
            NavigationModeController navigationModeController,
            Handler handler) {
        mContext = context;
        mWindowManager = windowManager;
        mViewCaptureAwareWindowManager = viewCaptureAwareWindowManager;
@@ -121,6 +123,7 @@ public class AccessibilityFloatingMenuController implements
        mSecureSettings = secureSettings;
        mDisplayTracker = displayTracker;
        mNavigationModeController = navigationModeController;
        mHandler = handler;

        mIsKeyguardVisible = false;
    }
@@ -159,6 +162,8 @@ public class AccessibilityFloatingMenuController implements
        mAccessibilityButtonModeObserver.addListener(this);
        mAccessibilityButtonTargetsObserver.addListener(this);
        mKeyguardUpdateMonitor.registerCallback(mKeyguardCallback);
        mAccessibilityManager.registerUserInitializationCompleteCallback(
                mUserInitializationCompleteCallback);
    }

    /**
@@ -172,7 +177,7 @@ public class AccessibilityFloatingMenuController implements
     */
    private void handleFloatingMenuVisibility(boolean keyguardVisible,
            @AccessibilityButtonMode int mode, String targets) {
        if (keyguardVisible) {
        if (keyguardVisible || mIsUserInInitialization) {
            destroyFloatingMenu();
            return;
        }
@@ -210,4 +215,18 @@ public class AccessibilityFloatingMenuController implements
        mFloatingMenu.hide();
        mFloatingMenu = null;
    }

    class UserInitializationCompleteCallback
            extends IUserInitializationCompleteCallback.Stub {
        @Override
        public void onUserInitializationComplete(int userId) {
            mIsUserInInitialization = false;
            mContext = mContext.createContextAsUser(UserHandle.of(userId), /* flags= */ 0);
            mBtnMode = mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode();
            mBtnTargets =
                    mAccessibilityButtonTargetsObserver.getCurrentAccessibilityButtonTargets();
            mHandler.post(
                    () -> handleFloatingMenuVisibility(mIsKeyguardVisible, mBtnMode, mBtnTargets));
        }
    }
}
+7 −2
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.ContextWrapper;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
import android.testing.TestableLooper;
@@ -80,6 +81,7 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase {
    private AccessibilityManager mAccessibilityManager;
    private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
    private AccessibilityFloatingMenuController mController;
    private TestableLooper mTestableLooper;
    @Mock
    private AccessibilityButtonTargetsObserver mTargetsObserver;
    @Mock
@@ -108,6 +110,7 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase {
        mViewCaptureAwareWindowManager = new ViewCaptureAwareWindowManager(mWindowManager,
                mLazyViewCapture, /* isViewCaptureEnabled= */ false);
        mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
        mTestableLooper = TestableLooper.get(this);

        when(mTargetsObserver.getCurrentAccessibilityButtonTargets())
                .thenReturn(Settings.Secure.getStringForUser(mContextWrapper.getContentResolver(),
@@ -231,7 +234,8 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase {
        mKeyguardCallback.onKeyguardVisibilityChanged(false);

        mKeyguardCallback.onUserSwitching(fakeUserId);
        mKeyguardCallback.onUserSwitchComplete(fakeUserId);
        mController.mUserInitializationCompleteCallback.onUserInitializationComplete(1);
        mTestableLooper.processAllMessages();

        assertThat(mController.mFloatingMenu).isNotNull();
    }
@@ -346,7 +350,8 @@ public class AccessibilityFloatingMenuControllerTest extends SysuiTestCase {
                new AccessibilityFloatingMenuController(mContextWrapper, windowManager,
                        viewCaptureAwareWindowManager, displayManager, mAccessibilityManager,
                        mTargetsObserver, mModeObserver, mKeyguardUpdateMonitor, mSecureSettings,
                        displayTracker, mNavigationModeController);
                        displayTracker, mNavigationModeController, new Handler(
                                mTestableLooper.getLooper()));
        controller.init();

        return controller;
Loading