diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/AlwaysOnMagnificationFeatureFlag.java b/services/accessibility/java/com/android/server/accessibility/magnification/AlwaysOnMagnificationFeatureFlag.java index 16d2e6b47a54c..93531ddea005b 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/AlwaysOnMagnificationFeatureFlag.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/AlwaysOnMagnificationFeatureFlag.java @@ -16,76 +16,31 @@ package com.android.server.accessibility.magnification; -import android.annotation.NonNull; import android.provider.DeviceConfig; -import com.android.internal.annotations.VisibleForTesting; - -import java.util.concurrent.Executor; - /** * Encapsulates the feature flags for always on magnification. {@see DeviceConfig} * * @hide */ -public class AlwaysOnMagnificationFeatureFlag { +public class AlwaysOnMagnificationFeatureFlag extends MagnificationFeatureFlagBase { private static final String NAMESPACE = DeviceConfig.NAMESPACE_WINDOW_MANAGER; private static final String FEATURE_NAME_ENABLE_ALWAYS_ON_MAGNIFICATION = "AlwaysOnMagnifier__enable_always_on_magnifier"; - private AlwaysOnMagnificationFeatureFlag() {} - - /** Returns true if the feature flag is enabled for always on magnification */ - public static boolean isAlwaysOnMagnificationEnabled() { - return DeviceConfig.getBoolean( - NAMESPACE, - FEATURE_NAME_ENABLE_ALWAYS_ON_MAGNIFICATION, - /* defaultValue= */ false); + @Override + String getNamespace() { + return NAMESPACE; } - /** Sets the feature flag. Only used for testing; requires shell permissions. */ - @VisibleForTesting - public static boolean setAlwaysOnMagnificationEnabled(boolean isEnabled) { - return DeviceConfig.setProperty( - NAMESPACE, - FEATURE_NAME_ENABLE_ALWAYS_ON_MAGNIFICATION, - Boolean.toString(isEnabled), - /* makeDefault= */ false); + @Override + String getFeatureName() { + return FEATURE_NAME_ENABLE_ALWAYS_ON_MAGNIFICATION; } - /** - * Adds a listener for when the feature flag changes. - * - *

{@see DeviceConfig#addOnPropertiesChangedListener( - * String, Executor, DeviceConfig.OnPropertiesChangedListener)} - */ - @NonNull - public static DeviceConfig.OnPropertiesChangedListener addOnChangedListener( - @NonNull Executor executor, @NonNull Runnable listener) { - DeviceConfig.OnPropertiesChangedListener onChangedListener = - properties -> { - if (properties.getKeyset().contains( - FEATURE_NAME_ENABLE_ALWAYS_ON_MAGNIFICATION)) { - listener.run(); - } - }; - DeviceConfig.addOnPropertiesChangedListener( - NAMESPACE, - executor, - onChangedListener); - - return onChangedListener; - } - - /** - * Remove a listener for when the feature flag changes. - * - *

{@see DeviceConfig#addOnPropertiesChangedListener(String, Executor, - * DeviceConfig.OnPropertiesChangedListener)} - */ - public static void removeOnChangedListener( - @NonNull DeviceConfig.OnPropertiesChangedListener onChangedListener) { - DeviceConfig.removeOnPropertiesChangedListener(onChangedListener); + @Override + boolean getDefaultValue() { + return false; } } diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java index ed8a35f45176e..fbc7b3cbc63b1 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java @@ -38,7 +38,6 @@ import android.graphics.Region; import android.hardware.display.DisplayManagerInternal; import android.os.Handler; import android.os.Message; -import android.provider.DeviceConfig; import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.MathUtils; @@ -57,6 +56,7 @@ 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; @@ -110,6 +110,7 @@ public class FullScreenMagnificationController implements private boolean mAlwaysOnMagnificationEnabled = false; private final DisplayManagerInternal mDisplayManagerInternal; + private final MagnificationThumbnailFeatureFlag mMagnificationThumbnailFeatureFlag; @NonNull private final Supplier mThumbnailSupplier; /** @@ -177,9 +178,7 @@ public class FullScreenMagnificationController implements mDisplayId, mMagnificationRegion); mMagnificationRegion.getBounds(mMagnificationBounds); - if (mMagnificationThumbnail == null) { - mMagnificationThumbnail = mThumbnailSupplier.get(); - } + createThumbnailIfSupported(); return true; } @@ -207,7 +206,7 @@ public class FullScreenMagnificationController implements mRegistered = false; unregisterCallbackLocked(mDisplayId, delete); - destroyThumbNail(); + destroyThumbnail(); } mUnregisterPending = false; } @@ -345,7 +344,7 @@ public class FullScreenMagnificationController implements mMagnificationRegion.set(magnified); mMagnificationRegion.getBounds(mMagnificationBounds); - refreshThumbNail(getScale(), getCenterX(), getCenterY()); + refreshThumbnail(getScale(), getCenterX(), getCenterY()); // It's possible that our magnification spec is invalid with the new bounds. // Adjust the current spec's offsets if necessary. @@ -405,9 +404,9 @@ public class FullScreenMagnificationController implements } if (isActivated()) { - updateThumbNail(scale, centerX, centerY); + updateThumbnail(scale, centerX, centerY); } else { - hideThumbNail(); + hideThumbnail(); } } @@ -538,7 +537,7 @@ public class FullScreenMagnificationController implements mIdOfLastServiceToMagnify = INVALID_SERVICE_ID; sendSpecToAnimation(spec, animationCallback); - hideThumbNail(); + hideThumbnail(); return changed; } @@ -596,16 +595,16 @@ public class FullScreenMagnificationController implements } @GuardedBy("mLock") - void updateThumbNail(float scale, float centerX, float centerY) { + void updateThumbnail(float scale, float centerX, float centerY) { if (mMagnificationThumbnail != null) { - mMagnificationThumbnail.updateThumbNail(scale, centerX, centerY); + mMagnificationThumbnail.updateThumbnail(scale, centerX, centerY); } } @GuardedBy("mLock") - void refreshThumbNail(float scale, float centerX, float centerY) { + void refreshThumbnail(float scale, float centerX, float centerY) { if (mMagnificationThumbnail != null) { - mMagnificationThumbnail.setThumbNailBounds( + mMagnificationThumbnail.setThumbnailBounds( mMagnificationBounds, scale, centerX, @@ -615,20 +614,38 @@ public class FullScreenMagnificationController implements } @GuardedBy("mLock") - void hideThumbNail() { + void hideThumbnail() { if (mMagnificationThumbnail != null) { - mMagnificationThumbnail.hideThumbNail(); + mMagnificationThumbnail.hideThumbnail(); } } @GuardedBy("mLock") - void destroyThumbNail() { + void createThumbnailIfSupported() { + if (mMagnificationThumbnail == null) { + mMagnificationThumbnail = mThumbnailSupplier.get(); + // We call refreshThumbnail when the thumbnail is just created to set current + // magnification bounds to thumbnail. It to prevent the thumbnail size has not yet + // updated properly and thus shows with huge size. (b/276314641) + refreshThumbnail(getScale(), getCenterX(), getCenterY()); + } + } + + @GuardedBy("mLock") + void destroyThumbnail() { if (mMagnificationThumbnail != null) { - hideThumbNail(); + hideThumbnail(); mMagnificationThumbnail = null; } } + void onThumbnailFeatureFlagChanged() { + synchronized (mLock) { + destroyThumbnail(); + createThumbnailIfSupported(); + } + } + /** * Updates the current magnification spec. * @@ -768,20 +785,7 @@ public class FullScreenMagnificationController implements lock, magnificationInfoChangedCallback, scaleProvider, - () -> { - if (DeviceConfig.getBoolean( - DeviceConfig.NAMESPACE_ACCESSIBILITY, - "enable_magnifier_thumbnail", - /* defaultValue= */ false)) { - return new MagnificationThumbnail( - context, - context.getSystemService(WindowManager.class), - new Handler(context.getMainLooper()) - ); - } - - return null; - }); + /* thumbnailSupplier= */ null); } /** Constructor for tests */ @@ -791,7 +795,7 @@ public class FullScreenMagnificationController implements @NonNull Object lock, @NonNull MagnificationInfoChangedCallback magnificationInfoChangedCallback, @NonNull MagnificationScaleProvider scaleProvider, - @NonNull Supplier thumbnailSupplier) { + Supplier thumbnailSupplier) { mControllerCtx = ctx; mLock = lock; mMainThreadId = mControllerCtx.getContext().getMainLooper().getThread().getId(); @@ -799,7 +803,41 @@ public class FullScreenMagnificationController implements addInfoChangedCallback(magnificationInfoChangedCallback); mScaleProvider = scaleProvider; mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); - mThumbnailSupplier = thumbnailSupplier; + mMagnificationThumbnailFeatureFlag = new MagnificationThumbnailFeatureFlag(); + mMagnificationThumbnailFeatureFlag.addOnChangedListener( + ConcurrentUtils.DIRECT_EXECUTOR, this::onMagnificationThumbnailFeatureFlagChanged); + if (thumbnailSupplier != null) { + mThumbnailSupplier = thumbnailSupplier; + } else { + mThumbnailSupplier = () -> { + if (mMagnificationThumbnailFeatureFlag.isFeatureFlagEnabled()) { + return new MagnificationThumbnail( + ctx.getContext(), + ctx.getContext().getSystemService(WindowManager.class), + new Handler(ctx.getContext().getMainLooper()) + ); + } + return null; + }; + } + } + + private void onMagnificationThumbnailFeatureFlagChanged() { + synchronized (mLock) { + for (int i = 0; i < mDisplays.size(); i++) { + onMagnificationThumbnailFeatureFlagChanged(mDisplays.keyAt(i)); + } + } + } + + private void onMagnificationThumbnailFeatureFlagChanged(int displayId) { + synchronized (mLock) { + final DisplayMagnification display = mDisplays.get(displayId); + if (display == null) { + return; + } + display.onThumbnailFeatureFlagChanged(); + } } /** diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java index c1c47f53ab7ec..7ee72dfa30fde 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java @@ -93,6 +93,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb private final SparseArray mMagnificationEndRunnableSparseArray = new SparseArray(); + private final AlwaysOnMagnificationFeatureFlag mAlwaysOnMagnificationFeatureFlag; private final MagnificationScaleProvider mScaleProvider; private FullScreenMagnificationController mFullScreenMagnificationController; private WindowMagnificationManager mWindowMagnificationMgr; @@ -151,7 +152,8 @@ public class MagnificationController implements WindowMagnificationManager.Callb mSupportWindowMagnification = context.getPackageManager().hasSystemFeature( FEATURE_WINDOW_MAGNIFICATION); - AlwaysOnMagnificationFeatureFlag.addOnChangedListener( + mAlwaysOnMagnificationFeatureFlag = new AlwaysOnMagnificationFeatureFlag(); + mAlwaysOnMagnificationFeatureFlag.addOnChangedListener( ConcurrentUtils.DIRECT_EXECUTOR, mAms::updateAlwaysOnMagnification); } @@ -710,7 +712,7 @@ public class MagnificationController implements WindowMagnificationManager.Callb } public boolean isAlwaysOnMagnificationFeatureFlagEnabled() { - return AlwaysOnMagnificationFeatureFlag.isAlwaysOnMagnificationEnabled(); + return mAlwaysOnMagnificationFeatureFlag.isFeatureFlagEnabled(); } private DisableMagnificationCallback getDisableMagnificationEndRunnableLocked( diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationFeatureFlagBase.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationFeatureFlagBase.java new file mode 100644 index 0000000000000..2965887d8eb3c --- /dev/null +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationFeatureFlagBase.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2023 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 com.android.server.accessibility.magnification; + +import android.annotation.NonNull; +import android.os.Binder; +import android.provider.DeviceConfig; + +import com.android.internal.annotations.VisibleForTesting; + +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Abstract base class to encapsulates the feature flags for magnification features. + * {@see DeviceConfig} + * + * @hide + */ +abstract class MagnificationFeatureFlagBase { + + abstract String getNamespace(); + abstract String getFeatureName(); + abstract boolean getDefaultValue(); + + private void clearCallingIdentifyAndTryCatch(Runnable tryBlock, Runnable catchBlock) { + try { + Binder.withCleanCallingIdentity(() -> tryBlock.run()); + } catch (Throwable throwable) { + catchBlock.run(); + } + } + + /** Returns true iff the feature flag is readable and enabled */ + public boolean isFeatureFlagEnabled() { + AtomicBoolean isEnabled = new AtomicBoolean(getDefaultValue()); + + clearCallingIdentifyAndTryCatch( + () -> isEnabled.set(DeviceConfig.getBoolean( + getNamespace(), + getFeatureName(), + getDefaultValue())), + () -> isEnabled.set(getDefaultValue())); + + return isEnabled.get(); + } + + /** Sets the feature flag. Only used for testing; requires shell permissions. */ + @VisibleForTesting + public boolean setFeatureFlagEnabled(boolean isEnabled) { + AtomicBoolean success = new AtomicBoolean(getDefaultValue()); + + clearCallingIdentifyAndTryCatch( + () -> success.set(DeviceConfig.setProperty( + getNamespace(), + getFeatureName(), + Boolean.toString(isEnabled), + /* makeDefault= */ false)), + () -> success.set(getDefaultValue())); + + return success.get(); + } + + /** + * Adds a listener for when the feature flag changes. + * + *

{@see DeviceConfig#addOnPropertiesChangedListener( + * String, Executor, DeviceConfig.OnPropertiesChangedListener)} + */ + @NonNull + public DeviceConfig.OnPropertiesChangedListener addOnChangedListener( + @NonNull Executor executor, @NonNull Runnable listener) { + DeviceConfig.OnPropertiesChangedListener onChangedListener = + properties -> { + if (properties.getKeyset().contains( + getFeatureName())) { + listener.run(); + } + }; + + clearCallingIdentifyAndTryCatch( + () -> DeviceConfig.addOnPropertiesChangedListener( + getNamespace(), + executor, + onChangedListener), + () -> {}); + + return onChangedListener; + } + + /** + * Remove a listener for when the feature flag changes. + * + *

{@see DeviceConfig#addOnPropertiesChangedListener(String, Executor, + * DeviceConfig.OnPropertiesChangedListener)} + */ + public void removeOnChangedListener( + @NonNull DeviceConfig.OnPropertiesChangedListener onChangedListener) { + DeviceConfig.removeOnPropertiesChangedListener(onChangedListener); + } +} diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationThumbnail.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationThumbnail.java index 5a783f47ccdc9..03fa93d8a3bc4 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationThumbnail.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationThumbnail.java @@ -58,7 +58,9 @@ public class MagnificationThumbnail { @VisibleForTesting public final FrameLayout mThumbnailLayout; - private final View mThumbNailView; + private final View mThumbnailView; + private int mThumbnailWidth; + private int mThumbnailHeight; private final WindowManager.LayoutParams mBackgroundParams; private boolean mVisible = false; @@ -66,7 +68,7 @@ public class MagnificationThumbnail { private static final float ASPECT_RATIO = 14f; private static final float BG_ASPECT_RATIO = ASPECT_RATIO / 2f; - private ObjectAnimator mThumbNailAnimator; + private ObjectAnimator mThumbnailAnimator; private boolean mIsFadingIn; /** @@ -79,9 +81,11 @@ public class MagnificationThumbnail { mWindowBounds = mWindowManager.getCurrentWindowMetrics().getBounds(); mThumbnailLayout = (FrameLayout) LayoutInflater.from(mContext) .inflate(R.layout.thumbnail_background_view, /* root: */ null); - mThumbNailView = + mThumbnailView = mThumbnailLayout.findViewById(R.id.accessibility_magnification_thumbnail_view); mBackgroundParams = createLayoutParams(); + mThumbnailWidth = 0; + mThumbnailHeight = 0; } /** @@ -90,35 +94,35 @@ public class MagnificationThumbnail { * @param currentBounds the current magnification bounds */ @AnyThread - public void setThumbNailBounds(Rect currentBounds, float scale, float centerX, float centerY) { + public void setThumbnailBounds(Rect currentBounds, float scale, float centerX, float centerY) { if (DEBUG) { - Log.d(LOG_TAG, "setThumbNailBounds " + currentBounds); + Log.d(LOG_TAG, "setThumbnailBounds " + currentBounds); } mHandler.post(() -> { mWindowBounds = currentBounds; setBackgroundBounds(); if (mVisible) { - updateThumbNailMainThread(scale, centerX, centerY); + updateThumbnailMainThread(scale, centerX, centerY); } }); } private void setBackgroundBounds() { Point magnificationBoundary = getMagnificationThumbnailPadding(mContext); - final int thumbNailWidth = (int) (mWindowBounds.width() / BG_ASPECT_RATIO); - final int thumbNailHeight = (int) (mWindowBounds.height() / BG_ASPECT_RATIO); + mThumbnailWidth = (int) (mWindowBounds.width() / BG_ASPECT_RATIO); + mThumbnailHeight = (int) (mWindowBounds.height() / BG_ASPECT_RATIO); int initX = magnificationBoundary.x; int initY = magnificationBoundary.y; - mBackgroundParams.width = thumbNailWidth; - mBackgroundParams.height = thumbNailHeight; + mBackgroundParams.width = mThumbnailWidth; + mBackgroundParams.height = mThumbnailHeight; mBackgroundParams.x = initX; mBackgroundParams.y = initY; } @MainThread - private void showThumbNail() { + private void showThumbnail() { if (DEBUG) { - Log.d(LOG_TAG, "showThumbNail " + mVisible); + Log.d(LOG_TAG, "showThumbnail " + mVisible); } animateThumbnail(true); } @@ -127,14 +131,14 @@ public class MagnificationThumbnail { * Hides thumbnail and removes the view from the window when finished animating. */ @AnyThread - public void hideThumbNail() { - mHandler.post(this::hideThumbNailMainThread); + public void hideThumbnail() { + mHandler.post(this::hideThumbnailMainThread); } @MainThread - private void hideThumbNailMainThread() { + private void hideThumbnailMainThread() { if (DEBUG) { - Log.d(LOG_TAG, "hideThumbNail " + mVisible); + Log.d(LOG_TAG, "hideThumbnail " + mVisible); } if (mVisible) { animateThumbnail(false); @@ -155,14 +159,14 @@ public class MagnificationThumbnail { + " fadeIn: " + fadeIn + " mVisible: " + mVisible + " isFadingIn: " + mIsFadingIn - + " isRunning: " + mThumbNailAnimator + + " isRunning: " + mThumbnailAnimator ); } // Reset countdown to hide automatically - mHandler.removeCallbacks(this::hideThumbNailMainThread); + mHandler.removeCallbacks(this::hideThumbnailMainThread); if (fadeIn) { - mHandler.postDelayed(this::hideThumbNailMainThread, LINGER_DURATION_MS); + mHandler.postDelayed(this::hideThumbnailMainThread, LINGER_DURATION_MS); } if (fadeIn == mIsFadingIn) { @@ -175,18 +179,18 @@ public class MagnificationThumbnail { mVisible = true; } - if (mThumbNailAnimator != null) { - mThumbNailAnimator.cancel(); + if (mThumbnailAnimator != null) { + mThumbnailAnimator.cancel(); } - mThumbNailAnimator = ObjectAnimator.ofFloat( + mThumbnailAnimator = ObjectAnimator.ofFloat( mThumbnailLayout, "alpha", fadeIn ? 1f : 0f ); - mThumbNailAnimator.setDuration( + mThumbnailAnimator.setDuration( fadeIn ? FADE_IN_ANIMATION_DURATION_MS : FADE_OUT_ANIMATION_DURATION_MS ); - mThumbNailAnimator.addListener(new Animator.AnimatorListener() { + mThumbnailAnimator.addListener(new Animator.AnimatorListener() { private boolean mIsCancelled; @Override @@ -231,7 +235,7 @@ public class MagnificationThumbnail { } }); - mThumbNailAnimator.start(); + mThumbnailAnimator.start(); } /** @@ -246,38 +250,48 @@ public class MagnificationThumbnail { * of the viewport, or {@link Float#NaN} to leave unchanged */ @AnyThread - public void updateThumbNail(float scale, float centerX, float centerY) { - mHandler.post(() -> updateThumbNailMainThread(scale, centerX, centerY)); + public void updateThumbnail(float scale, float centerX, float centerY) { + mHandler.post(() -> updateThumbnailMainThread(scale, centerX, centerY)); } @MainThread - private void updateThumbNailMainThread(float scale, float centerX, float centerY) { + private void updateThumbnailMainThread(float scale, float centerX, float centerY) { // Restart the fadeout countdown (or show if it's hidden) - showThumbNail(); + showThumbnail(); - var scaleDown = Float.isNaN(scale) ? mThumbNailView.getScaleX() : 1f / scale; + var scaleDown = Float.isNaN(scale) ? mThumbnailView.getScaleX() : 1f / scale; if (!Float.isNaN(scale)) { - mThumbNailView.setScaleX(scaleDown); - mThumbNailView.setScaleY(scaleDown); + mThumbnailView.setScaleX(scaleDown); + mThumbnailView.setScaleY(scaleDown); + } + float thumbnailWidth; + float thumbnailHeight; + if (mThumbnailView.getWidth() == 0 || mThumbnailView.getHeight() == 0) { + // if the thumbnail view size is not updated correctly, we just use the cached values. + thumbnailWidth = mThumbnailWidth; + thumbnailHeight = mThumbnailHeight; + } else { + thumbnailWidth = mThumbnailView.getWidth(); + thumbnailHeight = mThumbnailView.getHeight(); } if (!Float.isNaN(centerX)) { - var padding = mThumbNailView.getPaddingTop(); + var padding = mThumbnailView.getPaddingTop(); var ratio = 1f / BG_ASPECT_RATIO; - var centerXScaled = centerX * ratio - (mThumbNailView.getWidth() / 2f + padding); - var centerYScaled = centerY * ratio - (mThumbNailView.getHeight() / 2f + padding); + var centerXScaled = centerX * ratio - (thumbnailWidth / 2f + padding); + var centerYScaled = centerY * ratio - (thumbnailHeight / 2f + padding); if (DEBUG) { Log.d( LOG_TAG, - "updateThumbNail centerXScaled : " + centerXScaled + "updateThumbnail centerXScaled : " + centerXScaled + " centerYScaled : " + centerYScaled - + " getTranslationX : " + mThumbNailView.getTranslationX() + + " getTranslationX : " + mThumbnailView.getTranslationX() + " ratio : " + ratio ); } - mThumbNailView.setTranslationX(centerXScaled); - mThumbNailView.setTranslationY(centerYScaled); + mThumbnailView.setTranslationX(centerXScaled); + mThumbnailView.setTranslationY(centerYScaled); } } diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationThumbnailFeatureFlag.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationThumbnailFeatureFlag.java new file mode 100644 index 0000000000000..519f31b86f78a --- /dev/null +++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationThumbnailFeatureFlag.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023 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 com.android.server.accessibility.magnification; + +import android.provider.DeviceConfig; + +/** + * Encapsulates the feature flags for magnification thumbnail. {@see DeviceConfig} + * + * @hide + */ +public class MagnificationThumbnailFeatureFlag extends MagnificationFeatureFlagBase { + + private static final String NAMESPACE = DeviceConfig.NAMESPACE_ACCESSIBILITY; + private static final String FEATURE_NAME_ENABLE_MAGNIFIER_THUMBNAIL = + "enable_magnifier_thumbnail"; + + @Override + String getNamespace() { + return NAMESPACE; + } + + @Override + String getFeatureName() { + return FEATURE_NAME_ENABLE_MAGNIFIER_THUMBNAIL; + } + + @Override + boolean getDefaultValue() { + return false; + } +} diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java index f1ad577fde885..a01c7bdd51444 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java @@ -200,7 +200,7 @@ public class FullScreenMagnificationControllerTest { assertFalse(mFullScreenMagnificationController.isRegistered(DISPLAY_0)); assertFalse(mFullScreenMagnificationController.isRegistered(DISPLAY_1)); - verify(mMockThumbnail, times(2)).hideThumbNail(); + verify(mMockThumbnail, times(2)).hideThumbnail(); } @Test @@ -538,7 +538,10 @@ public class FullScreenMagnificationControllerTest { mConfigCaptor.capture()); assertConfigEquals(config, mConfigCaptor.getValue()); - verify(mMockThumbnail).setThumbNailBounds(any(), anyFloat(), anyFloat(), anyFloat()); + // The first time is triggered when the thumbnail is just created. + // The second time is triggered when the magnification region changed. + verify(mMockThumbnail, times(2)).setThumbnailBounds( + any(), anyFloat(), anyFloat(), anyFloat()); } @Test @@ -909,7 +912,7 @@ public class FullScreenMagnificationControllerTest { verifyNoMoreInteractions(mMockWindowManager); verify(mMockThumbnail) - .updateThumbNail(eq(scale), eq(startCenter.x), eq(startCenter.y)); + .updateThumbnail(eq(scale), eq(startCenter.x), eq(startCenter.y)); } @Test diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationThumbnailTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationThumbnailTest.java index 60c8148180da4..3baa102b882b4 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationThumbnailTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationThumbnailTest.java @@ -66,14 +66,14 @@ public class MagnificationThumbnailTest { @Test public void updateThumbnailShows() { - runOnMainSync(() -> mMagnificationThumbnail.updateThumbNail( + runOnMainSync(() -> mMagnificationThumbnail.updateThumbnail( /* scale= */ 2f, /* centerX= */ 5, /* centerY= */ 10 )); idle(); - runOnMainSync(() -> mMagnificationThumbnail.updateThumbNail( + runOnMainSync(() -> mMagnificationThumbnail.updateThumbnail( /* scale= */ 2.2f, /* centerX= */ 15, /* centerY= */ 50 @@ -86,7 +86,7 @@ public class MagnificationThumbnailTest { @Test public void updateThumbnailLingersThenHidesAfterTimeout() throws InterruptedException { - runOnMainSync(() -> mMagnificationThumbnail.updateThumbNail( + runOnMainSync(() -> mMagnificationThumbnail.updateThumbnail( /* scale= */ 2f, /* centerX= */ 5, /* centerY= */ 10 @@ -103,14 +103,14 @@ public class MagnificationThumbnailTest { @Test public void hideThumbnailRemoves() throws InterruptedException { - runOnMainSync(() -> mMagnificationThumbnail.updateThumbNail( + runOnMainSync(() -> mMagnificationThumbnail.updateThumbnail( /* scale= */ 2f, /* centerX= */ 5, /* centerY= */ 10 )); idle(); - runOnMainSync(() -> mMagnificationThumbnail.hideThumbNail()); + runOnMainSync(() -> mMagnificationThumbnail.hideThumbnail()); idle(); // Wait for the fade out animation @@ -122,10 +122,10 @@ public class MagnificationThumbnailTest { @Test public void hideShowHideShowHideRemoves() throws InterruptedException { - runOnMainSync(() -> mMagnificationThumbnail.hideThumbNail()); + runOnMainSync(() -> mMagnificationThumbnail.hideThumbnail()); idle(); - runOnMainSync(() -> mMagnificationThumbnail.updateThumbNail( + runOnMainSync(() -> mMagnificationThumbnail.updateThumbnail( /* scale= */ 2f, /* centerX= */ 5, /* centerY= */ 10 @@ -135,17 +135,17 @@ public class MagnificationThumbnailTest { // Wait for the fade in animation Thread.sleep(200L); - runOnMainSync(() -> mMagnificationThumbnail.hideThumbNail()); + runOnMainSync(() -> mMagnificationThumbnail.hideThumbnail()); idle(); - runOnMainSync(() -> mMagnificationThumbnail.updateThumbNail( + runOnMainSync(() -> mMagnificationThumbnail.updateThumbnail( /* scale= */ 2f, /* centerX= */ 5, /* centerY= */ 10 )); idle(); - runOnMainSync(() -> mMagnificationThumbnail.hideThumbNail()); + runOnMainSync(() -> mMagnificationThumbnail.hideThumbnail()); idle(); @@ -158,7 +158,7 @@ public class MagnificationThumbnailTest { @Test public void hideWithoutShowDoesNothing() throws InterruptedException { - runOnMainSync(() -> mMagnificationThumbnail.hideThumbNail()); + runOnMainSync(() -> mMagnificationThumbnail.hideThumbnail()); idle(); // Wait for the fade out animation @@ -172,7 +172,7 @@ public class MagnificationThumbnailTest { @Test public void whenHidden_setBoundsDoesNotShow() throws InterruptedException { - runOnMainSync(() -> mMagnificationThumbnail.setThumbNailBounds( + runOnMainSync(() -> mMagnificationThumbnail.setThumbnailBounds( new Rect(), /* scale= */ 2f, /* centerX= */ 5,