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

Commit 502de117 authored by Roy Chou's avatar Roy Chou
Browse files

chore(magnification): add magnification sysui connection state changed callback for cts tests

In accessibility magnification cts tests we need to ensure the
magnification system ui connection is ready for the coming tests.
Therefore in AccessibilityService#dispatchServiceConnected we add a
conditional magnification sysui connection state check, so if the
service find itself has capability to control magnification, it will
wait until the magnification sysui connection is ready then trigger
onServiceConnected callback.

The fix is gated with a bug-fix flag so we can verify it with rollout
process.

Bug: 337800504
Flag: ACONFIG android.view.accessibility.wait_magnification_system_ui_connection_to_notify_service_connected DEVELOPMENT
Test: pass build
      atest AccessibilityMagnificationTest
Change-Id: I3e38ba32515eadd8f5eac6aa5fd906eeb25e24c9
parent 29acc19f
Loading
Loading
Loading
Loading
+97 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.accessibilityservice;

import static android.accessibilityservice.AccessibilityServiceInfo.CAPABILITY_CAN_CONTROL_MAGNIFICATION;
import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;

@@ -69,6 +70,8 @@ import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.accessibility.AccessibilityWindowInfo;
import android.view.inputmethod.EditorInfo;

import androidx.annotation.GuardedBy;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.inputmethod.CancellationGroup;
import com.android.internal.inputmethod.IAccessibilityInputMethodSession;
@@ -640,6 +643,8 @@ public abstract class AccessibilityService extends Service {
        /** The detected gesture information for different displays */
        boolean onGesture(AccessibilityGestureEvent gestureInfo);
        boolean onKeyEvent(KeyEvent event);
        /** Magnification SystemUI connection changed callbacks */
        void onMagnificationSystemUIConnectionChanged(boolean connected);
        /** Magnification changed callbacks for different displays */
        void onMagnificationChanged(int displayId, @NonNull Region region,
                MagnificationConfig config);
@@ -790,7 +795,6 @@ public abstract class AccessibilityService extends Service {
    public static final String KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP =
            "screenshot_timestamp";


    /**
     * Annotations for result codes of attaching accessibility overlays.
     *
@@ -837,6 +841,13 @@ public abstract class AccessibilityService extends Service {

    private WindowManager mWindowManager;

    @GuardedBy("mLock")
    private boolean mServiceConnected;
    @GuardedBy("mLock")
    private boolean mMagnificationSystemUIConnected;
    @GuardedBy("mLock")
    private boolean mServiceConnectedNotified;

    /** List of magnification controllers, mapping from displayId -> MagnificationController. */
    private final SparseArray<MagnificationController> mMagnificationControllers =
            new SparseArray<>(0);
@@ -886,11 +897,14 @@ public abstract class AccessibilityService extends Service {
            for (int i = 0; i < mMagnificationControllers.size(); i++) {
                mMagnificationControllers.valueAt(i).onServiceConnectedLocked();
            }
            checkIsMagnificationSystemUIConnectedAlready();
            final AccessibilityServiceInfo info = getServiceInfo();
            if (info != null) {
                updateInputMethod(info);
                mMotionEventSources = info.getMotionEventSources();
            }
            mServiceConnected = true;
            mServiceConnectedNotified = false;
        }
        if (mSoftKeyboardController != null) {
            mSoftKeyboardController.onServiceConnected();
@@ -898,8 +912,58 @@ public abstract class AccessibilityService extends Service {

        // The client gets to handle service connection last, after we've set
        // up any state upon which their code may rely.
        if (android.view.accessibility.Flags
                .waitMagnificationSystemUiConnectionToNotifyServiceConnected()) {
            notifyOnServiceConnectedIfReady();
        } else {
            onServiceConnected();
        }
    }

    private void notifyOnServiceConnectedIfReady() {
        synchronized (mLock) {
            if (mServiceConnectedNotified) {
                return;
            }
            boolean canControlMagnification;
            final AccessibilityServiceInfo info = getServiceInfo();
            if (info != null) {
                int flagMask = CAPABILITY_CAN_CONTROL_MAGNIFICATION;
                canControlMagnification = (info.getCapabilities() & flagMask) == flagMask;
            } else {
                canControlMagnification = false;
            }
            boolean ready = canControlMagnification
                    ? (mServiceConnected && mMagnificationSystemUIConnected)
                    : mServiceConnected;
            if (ready) {
                getMainExecutor().execute(() -> onServiceConnected());
                mServiceConnectedNotified = true;
            }
        }
    }

    @GuardedBy("mLock")
    private void checkIsMagnificationSystemUIConnectedAlready() {
        if (!android.view.accessibility.Flags
                .waitMagnificationSystemUiConnectionToNotifyServiceConnected()) {
            return;
        }
        if (mMagnificationSystemUIConnected) {
            return;
        }
        final IAccessibilityServiceConnection connection =
                AccessibilityInteractionClient.getInstance(this).getConnection(mConnectionId);
        if (connection != null) {
            try {
                boolean connected = connection.isMagnificationSystemUIConnected();
                mMagnificationSystemUIConnected = connected;
            } catch (RemoteException re) {
                Log.w(LOG_TAG, "Failed to check magnification system ui connection", re);
                re.rethrowFromSystemServer();
            }
        }
    }

    private void updateInputMethod(AccessibilityServiceInfo info) {
        if (info != null) {
@@ -1360,6 +1424,22 @@ public abstract class AccessibilityService extends Service {
        }
    }

    private void onMagnificationSystemUIConnectionChanged(boolean connected) {
        if (!android.view.accessibility.Flags
                .waitMagnificationSystemUiConnectionToNotifyServiceConnected()) {
            return;
        }

        synchronized (mLock) {
            boolean changed = (mMagnificationSystemUIConnected != connected);
            mMagnificationSystemUIConnected = connected;

            if (changed) {
                notifyOnServiceConnectedIfReady();
            }
        }
    }

    private void onMagnificationChanged(int displayId, @NonNull Region region,
            MagnificationConfig config) {
        MagnificationController controller;
@@ -2822,6 +2902,11 @@ public abstract class AccessibilityService extends Service {
                return AccessibilityService.this.onKeyEvent(event);
            }

            @Override
            public void onMagnificationSystemUIConnectionChanged(boolean connected) {
                AccessibilityService.this.onMagnificationSystemUIConnectionChanged(connected);
            }

            @Override
            public void onMagnificationChanged(int displayId, @NonNull Region region,
                    MagnificationConfig config) {
@@ -3032,6 +3117,16 @@ public abstract class AccessibilityService extends Service {
            });
        }

        @Override
        public void onMagnificationSystemUIConnectionChanged(boolean connected) {
            mExecutor.execute(() -> {
                if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
                    mCallback.onMagnificationSystemUIConnectionChanged(connected);
                }
                return;
            });
        }

        /** Magnification changed callbacks for different displays */
        public void onMagnificationChanged(int displayId, @NonNull Region region,
                MagnificationConfig config) {
+2 −0
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;

    void onKeyEvent(in KeyEvent event, int sequence);

    void onMagnificationSystemUIConnectionChanged(boolean connected);

    void onMagnificationChanged(int displayId, in Region region, in MagnificationConfig config);

    void onMotionEvent(in MotionEvent event);
+3 −0
Original line number Diff line number Diff line
@@ -129,6 +129,9 @@ interface IAccessibilityServiceConnection {
    @RequiresNoPermission
    void setMagnificationCallbackEnabled(int displayId, boolean enabled);

    @RequiresNoPermission
    boolean isMagnificationSystemUIConnected();

    @RequiresNoPermission
    boolean setSoftKeyboardShowMode(int showMode);

+5 −0
Original line number Diff line number Diff line
@@ -1968,6 +1968,11 @@ public final class UiAutomation {
                    return false;
                }

                @Override
                public void onMagnificationSystemUIConnectionChanged(boolean connected) {
                    /* do nothing */
                }

                @Override
                public void onMagnificationChanged(int displayId, @NonNull Region region,
                        MagnificationConfig config) {
+4 −0
Original line number Diff line number Diff line
@@ -301,6 +301,10 @@ public abstract class AccessibilityDisplayProxy {
                    return false;
                }

                @Override
                public void onMagnificationSystemUIConnectionChanged(boolean connected) {
                }

                @Override
                public void onMagnificationChanged(int displayId, @NonNull Region region,
                        MagnificationConfig config) {
Loading