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

Commit 91d351bf authored by Tyler Freeman's avatar Tyler Freeman
Browse files

fix(magnifier): fix deadlock when feature flag changes

Handle feature flag changes on a background thread so we're not blocking
the main thread which might already be locked.

Fix: 281132229
Test: 0. Complete initial SUW without connecting WiFi, no account added and no lock screen set.
1. On target device, tap on deferred SUW notification and proceed.
2. Tap on "Get started" on Welcome screen. Quick Start User Guide screen is displayed.
3. Connect source and target devices by scanning the QR Code with scanner
4. WiFi setting is transferred and the target device connected to internet. Getting your phone ready screen is shown
6. Wait and observe. SysUi should not hang / black screen.

Change-Id: Ic2cf5cfb34041671468f0036a243e24005d064c9
parent 9aa7ca07
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -179,6 +179,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -494,8 +495,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
        mA11yWindowManager = new AccessibilityWindowManager(mLock, mMainHandler,
                mWindowManagerService, this, mSecurityPolicy, this, mTraceManager);
        mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler);
        mMagnificationController = new MagnificationController(this, mLock, mContext,
                new MagnificationScaleProvider(mContext));
        mMagnificationController = new MagnificationController(
                this,
                mLock,
                mContext,
                new MagnificationScaleProvider(mContext),
                Executors.newSingleThreadExecutor()
        );
        mMagnificationProcessor = new MagnificationProcessor(mMagnificationController);
        mCaptioningManagerImpl = new CaptioningManagerImpl(mContext);
        mProxyManager = new ProxyManager(mLock, mA11yWindowManager, mContext, mMainHandler,
+8 −5
Original line number Diff line number Diff line
@@ -56,7 +56,6 @@ import com.android.internal.R;
import com.android.internal.accessibility.common.MagnificationConstants;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityManagerService;
@@ -65,6 +64,7 @@ import com.android.server.wm.WindowManagerInternal;

import java.util.ArrayList;
import java.util.Locale;
import java.util.concurrent.Executor;
import java.util.function.Supplier;

/**
@@ -774,7 +774,8 @@ public class FullScreenMagnificationController implements
    public FullScreenMagnificationController(@NonNull Context context,
            @NonNull AccessibilityTraceManager traceManager, @NonNull Object lock,
            @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback,
            @NonNull MagnificationScaleProvider scaleProvider) {
            @NonNull MagnificationScaleProvider scaleProvider,
            @NonNull Executor backgroundExecutor) {
        this(
                new ControllerContext(
                        context,
@@ -785,7 +786,8 @@ public class FullScreenMagnificationController implements
                lock,
                magnificationInfoChangedCallback,
                scaleProvider,
                /* thumbnailSupplier= */ null);
                /* thumbnailSupplier= */ null,
                backgroundExecutor);
    }

    /** Constructor for tests */
@@ -795,7 +797,8 @@ public class FullScreenMagnificationController implements
            @NonNull Object lock,
            @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback,
            @NonNull MagnificationScaleProvider scaleProvider,
            Supplier<MagnificationThumbnail> thumbnailSupplier) {
            Supplier<MagnificationThumbnail> thumbnailSupplier,
            @NonNull Executor backgroundExecutor) {
        mControllerCtx = ctx;
        mLock = lock;
        mMainThreadId = mControllerCtx.getContext().getMainLooper().getThread().getId();
@@ -805,7 +808,7 @@ public class FullScreenMagnificationController implements
        mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
        mMagnificationThumbnailFeatureFlag = new MagnificationThumbnailFeatureFlag();
        mMagnificationThumbnailFeatureFlag.addOnChangedListener(
                ConcurrentUtils.DIRECT_EXECUTOR, this::onMagnificationThumbnailFeatureFlagChanged);
                backgroundExecutor, this::onMagnificationThumbnailFeatureFlagChanged);
        if (thumbnailSupplier != null) {
            mThumbnailSupplier = thumbnailSupplier;
        } else {
+18 −8
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK;

import static com.android.server.accessibility.AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID;

@@ -48,11 +47,12 @@ import android.view.accessibility.MagnificationAnimationCallback;
import com.android.internal.accessibility.util.AccessibilityStatsLogUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ConcurrentUtils;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.wm.WindowManagerInternal;

import java.util.concurrent.Executor;

/**
 * Handles all magnification controllers initialization, generic interactions,
 * magnification mode transition and magnification switch UI show/hide logic
@@ -101,6 +101,8 @@ public class MagnificationController implements WindowMagnificationManager.Callb
    /** Whether the platform supports window magnification feature. */
    private final boolean mSupportWindowMagnification;

    private final Executor mBackgroundExecutor;

    @GuardedBy("mLock")
    private final SparseIntArray mCurrentMagnificationModeArray = new SparseIntArray();
    @GuardedBy("mLock")
@@ -142,11 +144,13 @@ public class MagnificationController implements WindowMagnificationManager.Callb
    }

    public MagnificationController(AccessibilityManagerService ams, Object lock,
            Context context, MagnificationScaleProvider scaleProvider) {
            Context context, MagnificationScaleProvider scaleProvider,
            Executor backgroundExecutor) {
        mAms = ams;
        mLock = lock;
        mContext = context;
        mScaleProvider = scaleProvider;
        mBackgroundExecutor = backgroundExecutor;
        LocalServices.getService(WindowManagerInternal.class)
                .getAccessibilityController().setUiChangesForAccessibilityCallbacks(this);
        mSupportWindowMagnification = context.getPackageManager().hasSystemFeature(
@@ -154,15 +158,15 @@ public class MagnificationController implements WindowMagnificationManager.Callb

        mAlwaysOnMagnificationFeatureFlag = new AlwaysOnMagnificationFeatureFlag();
        mAlwaysOnMagnificationFeatureFlag.addOnChangedListener(
                ConcurrentUtils.DIRECT_EXECUTOR, mAms::updateAlwaysOnMagnification);
                mBackgroundExecutor, mAms::updateAlwaysOnMagnification);
    }

    @VisibleForTesting
    public MagnificationController(AccessibilityManagerService ams, Object lock,
            Context context, FullScreenMagnificationController fullScreenMagnificationController,
            WindowMagnificationManager windowMagnificationManager,
            MagnificationScaleProvider scaleProvider) {
        this(ams, lock, context, scaleProvider);
            MagnificationScaleProvider scaleProvider, Executor backgroundExecutor) {
        this(ams, lock, context, scaleProvider, backgroundExecutor);
        mFullScreenMagnificationController = fullScreenMagnificationController;
        mWindowMagnificationMgr = windowMagnificationManager;
    }
@@ -757,8 +761,14 @@ public class MagnificationController implements WindowMagnificationManager.Callb
    public FullScreenMagnificationController getFullScreenMagnificationController() {
        synchronized (mLock) {
            if (mFullScreenMagnificationController == null) {
                mFullScreenMagnificationController = new FullScreenMagnificationController(mContext,
                        mAms.getTraceManager(), mLock, this, mScaleProvider);
                mFullScreenMagnificationController = new FullScreenMagnificationController(
                        mContext,
                        mAms.getTraceManager(),
                        mLock,
                        this,
                        mScaleProvider,
                        mBackgroundExecutor
                );
            }
        }
        return mFullScreenMagnificationController;
+3 −0
Original line number Diff line number Diff line
@@ -80,6 +80,9 @@ abstract class MagnificationFeatureFlagBase {
     *
     * <p>{@see DeviceConfig#addOnPropertiesChangedListener(
     * String, Executor, DeviceConfig.OnPropertiesChangedListener)}
     *
     * <p>Note: be weary of using a DIRECT_EXECUTOR here. You may run into deadlocks! (see
     * b/281132229)
     */
    @NonNull
    public DeviceConfig.OnPropertiesChangedListener addOnChangedListener(
+3 −1
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ import android.view.accessibility.MagnificationAnimationCallback;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityTraceManager;
@@ -160,7 +161,8 @@ public class FullScreenMagnificationControllerTest {
                        new Object(),
                        mRequestObserver,
                        mScaleProvider,
                        () -> mMockThumbnail);
                        () -> mMockThumbnail,
                        ConcurrentUtils.DIRECT_EXECUTOR);
    }

    @After
Loading