Merge changes from topic "new-ohm-bg-panel"
* changes: (2/n) Implement BackgroundWindowManager to manage tutorial background (1/n) Phase out FEATURE_ONE_HANDED_BACKGROUND_PANEL
This commit is contained in:
@@ -100,14 +100,6 @@ public class DisplayAreaOrganizer extends WindowOrganizer {
|
||||
*/
|
||||
public static final int FEATURE_IME_PLACEHOLDER = FEATURE_SYSTEM_FIRST + 7;
|
||||
|
||||
/**
|
||||
* Display area for one handed background layer, which preventing when user
|
||||
* turning the Dark theme on, they can not clearly identify the screen has entered
|
||||
* one handed mode.
|
||||
* @hide
|
||||
*/
|
||||
public static final int FEATURE_ONE_HANDED_BACKGROUND_PANEL = FEATURE_SYSTEM_FIRST + 8;
|
||||
|
||||
/**
|
||||
* Display area hosting IME window tokens (@see ImeContainer). By default, IMEs are parented
|
||||
* to FEATURE_IME_PLACEHOLDER but can be reparented under other RootDisplayArea.
|
||||
@@ -118,7 +110,7 @@ public class DisplayAreaOrganizer extends WindowOrganizer {
|
||||
* app on another screen).
|
||||
* @hide
|
||||
*/
|
||||
public static final int FEATURE_IME = FEATURE_SYSTEM_FIRST + 9;
|
||||
public static final int FEATURE_IME = FEATURE_SYSTEM_FIRST + 8;
|
||||
|
||||
/**
|
||||
* The last boundary of display area for system features
|
||||
|
||||
26
libs/WindowManager/Shell/res/layout/background_panel.xml
Normal file
26
libs/WindowManager/Shell/res/layout/background_panel.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
~ Copyright (C) 2022 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
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/background_panel_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center_horizontal | center_vertical"
|
||||
android:background="@android:color/transparent">
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.wm.shell.onehanded;
|
||||
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
|
||||
|
||||
import static com.android.wm.shell.onehanded.OneHandedState.STATE_ACTIVE;
|
||||
import static com.android.wm.shell.onehanded.OneHandedState.STATE_ENTERING;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Binder;
|
||||
import android.util.Slog;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.IWindow;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceControlViewHost;
|
||||
import android.view.SurfaceSession;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowlessWindowManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.wm.shell.R;
|
||||
import com.android.wm.shell.common.DisplayLayout;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* Holds view hierarchy of a root surface and helps inflate a themeable view for background.
|
||||
*/
|
||||
public final class BackgroundWindowManager extends WindowlessWindowManager {
|
||||
private static final String TAG = BackgroundWindowManager.class.getSimpleName();
|
||||
private static final int THEME_COLOR_OFFSET = 10;
|
||||
|
||||
private final OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory
|
||||
mTransactionFactory;
|
||||
|
||||
private Context mContext;
|
||||
private Rect mDisplayBounds;
|
||||
private SurfaceControlViewHost mViewHost;
|
||||
private SurfaceControl mLeash;
|
||||
private View mBackgroundView;
|
||||
private @OneHandedState.State int mCurrentState;
|
||||
|
||||
public BackgroundWindowManager(Context context) {
|
||||
super(context.getResources().getConfiguration(), null /* rootSurface */,
|
||||
null /* hostInputToken */);
|
||||
mContext = context;
|
||||
mTransactionFactory = SurfaceControl.Transaction::new;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SurfaceControl getSurfaceControl(IWindow window) {
|
||||
return super.getSurfaceControl(window);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfiguration(Configuration configuration) {
|
||||
super.setConfiguration(configuration);
|
||||
mContext = mContext.createConfigurationContext(configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* onConfigurationChanged events for updating background theme color.
|
||||
*/
|
||||
public void onConfigurationChanged() {
|
||||
if (mCurrentState == STATE_ENTERING || mCurrentState == STATE_ACTIVE) {
|
||||
updateThemeOnly();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* One-handed mode state changed callback
|
||||
* @param newState of One-handed mode representing by {@link OneHandedState}
|
||||
*/
|
||||
public void onStateChanged(int newState) {
|
||||
mCurrentState = newState;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
|
||||
final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
|
||||
.setColorLayer()
|
||||
.setBufferSize(mDisplayBounds.width(), mDisplayBounds.height())
|
||||
.setFormat(PixelFormat.RGB_888)
|
||||
.setOpaque(true)
|
||||
.setName(TAG)
|
||||
.setCallsite("BackgroundWindowManager#attachToParentSurface");
|
||||
mLeash = builder.build();
|
||||
b.setParent(mLeash);
|
||||
}
|
||||
|
||||
/** Inflates background view on to the root surface. */
|
||||
boolean initView() {
|
||||
if (mBackgroundView != null || mViewHost != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
|
||||
mBackgroundView = (View) LayoutInflater.from(mContext)
|
||||
.inflate(R.layout.background_panel, null /* root */);
|
||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
||||
mDisplayBounds.width(), mDisplayBounds.height(), 0 /* TYPE NONE */,
|
||||
FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL | FLAG_WATCH_OUTSIDE_TOUCH
|
||||
| FLAG_SLIPPERY, PixelFormat.TRANSLUCENT);
|
||||
lp.token = new Binder();
|
||||
lp.setTitle("background-panel");
|
||||
lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
|
||||
mBackgroundView.setBackgroundColor(getThemeColorForBackground());
|
||||
mViewHost.setView(mBackgroundView, lp);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when onDisplayAdded() or onDisplayRemoved() callback.
|
||||
* @param displayLayout The latest {@link DisplayLayout} for display bounds.
|
||||
*/
|
||||
public void onDisplayChanged(DisplayLayout displayLayout) {
|
||||
// One-handed mode is only available on portrait.
|
||||
if (displayLayout.height() > displayLayout.width()) {
|
||||
mDisplayBounds = new Rect(0, 0, displayLayout.width(), displayLayout.height());
|
||||
} else {
|
||||
mDisplayBounds = new Rect(0, 0, displayLayout.height(), displayLayout.width());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateThemeOnly() {
|
||||
if (mBackgroundView == null || mViewHost == null || mLeash == null) {
|
||||
Slog.w(TAG, "Background view or SurfaceControl does not exist when trying to "
|
||||
+ "update theme only!");
|
||||
return;
|
||||
}
|
||||
|
||||
WindowManager.LayoutParams lp = (WindowManager.LayoutParams)
|
||||
mBackgroundView.getLayoutParams();
|
||||
mBackgroundView.setBackgroundColor(getThemeColorForBackground());
|
||||
mViewHost.setView(mBackgroundView, lp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the background layer when One-handed mode triggered.
|
||||
*/
|
||||
public void showBackgroundLayer() {
|
||||
if (!initView()) {
|
||||
updateThemeOnly();
|
||||
return;
|
||||
}
|
||||
if (mLeash == null) {
|
||||
Slog.w(TAG, "SurfaceControl mLeash is null, can't show One-handed mode "
|
||||
+ "background panel!");
|
||||
return;
|
||||
}
|
||||
|
||||
mTransactionFactory.getTransaction()
|
||||
.setAlpha(mLeash, 1.0f)
|
||||
.setLayer(mLeash, -1 /* at bottom-most layer */)
|
||||
.show(mLeash)
|
||||
.apply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the leash of background layer after stop One-handed mode.
|
||||
*/
|
||||
public void removeBackgroundLayer() {
|
||||
if (mBackgroundView != null) {
|
||||
mBackgroundView = null;
|
||||
}
|
||||
|
||||
if (mViewHost != null) {
|
||||
mViewHost.release();
|
||||
mViewHost = null;
|
||||
}
|
||||
|
||||
if (mLeash != null) {
|
||||
mTransactionFactory.getTransaction().remove(mLeash).apply();
|
||||
mLeash = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets {@link SurfaceControl} of the background layer.
|
||||
* @return {@code null} if not exist.
|
||||
*/
|
||||
@Nullable
|
||||
SurfaceControl getSurfaceControl() {
|
||||
return mLeash;
|
||||
}
|
||||
|
||||
private int getThemeColor() {
|
||||
final Context themedContext = new ContextThemeWrapper(mContext,
|
||||
com.android.internal.R.style.Theme_DeviceDefault_DayNight);
|
||||
return themedContext.getColor(R.color.one_handed_tutorial_background_color);
|
||||
}
|
||||
|
||||
int getThemeColorForBackground() {
|
||||
final int origThemeColor = getThemeColor();
|
||||
return android.graphics.Color.argb(Color.alpha(origThemeColor),
|
||||
Color.red(origThemeColor) - THEME_COLOR_OFFSET,
|
||||
Color.green(origThemeColor) - THEME_COLOR_OFFSET,
|
||||
Color.blue(origThemeColor) - THEME_COLOR_OFFSET);
|
||||
}
|
||||
|
||||
private float adjustColor(int origColor) {
|
||||
return Math.max(origColor - THEME_COLOR_OFFSET, 0) / 255.0f;
|
||||
}
|
||||
|
||||
void dump(@NonNull PrintWriter pw) {
|
||||
final String innerPrefix = " ";
|
||||
pw.println(TAG);
|
||||
pw.print(innerPrefix + "mDisplayBounds=");
|
||||
pw.println(mDisplayBounds);
|
||||
pw.print(innerPrefix + "mViewHost=");
|
||||
pw.println(mViewHost);
|
||||
pw.print(innerPrefix + "mLeash=");
|
||||
pw.println(mLeash);
|
||||
pw.print(innerPrefix + "mBackgroundView=");
|
||||
pw.println(mBackgroundView);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,272 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.wm.shell.onehanded;
|
||||
|
||||
import static com.android.wm.shell.onehanded.OneHandedState.STATE_ACTIVE;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceSession;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.window.DisplayAreaAppearedInfo;
|
||||
import android.window.DisplayAreaInfo;
|
||||
import android.window.DisplayAreaOrganizer;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.wm.shell.R;
|
||||
import com.android.wm.shell.common.DisplayLayout;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* Manages OneHanded color background layer areas.
|
||||
* To avoid when turning the Dark theme on, users can not clearly identify
|
||||
* the screen has entered one handed mode.
|
||||
*/
|
||||
public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer
|
||||
implements OneHandedAnimationCallback, OneHandedState.OnStateChangedListener {
|
||||
private static final String TAG = "OneHandedBackgroundPanelOrganizer";
|
||||
private static final int THEME_COLOR_OFFSET = 10;
|
||||
private static final int ALPHA_ANIMATION_DURATION = 200;
|
||||
|
||||
private final Context mContext;
|
||||
private final SurfaceSession mSurfaceSession = new SurfaceSession();
|
||||
private final OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory
|
||||
mTransactionFactory;
|
||||
|
||||
private @OneHandedState.State int mCurrentState;
|
||||
private ValueAnimator mAlphaAnimator;
|
||||
|
||||
private float mTranslationFraction;
|
||||
private float[] mThemeColor;
|
||||
|
||||
/**
|
||||
* The background to distinguish the boundary of translated windows and empty region when
|
||||
* one handed mode triggered.
|
||||
*/
|
||||
private Rect mBkgBounds;
|
||||
private Rect mStableInsets;
|
||||
|
||||
@Nullable
|
||||
@VisibleForTesting
|
||||
SurfaceControl mBackgroundSurface;
|
||||
@Nullable
|
||||
private SurfaceControl mParentLeash;
|
||||
|
||||
public OneHandedBackgroundPanelOrganizer(Context context, DisplayLayout displayLayout,
|
||||
OneHandedSettingsUtil settingsUtil, Executor executor) {
|
||||
super(executor);
|
||||
mContext = context;
|
||||
mTranslationFraction = settingsUtil.getTranslationFraction(context);
|
||||
mTransactionFactory = SurfaceControl.Transaction::new;
|
||||
updateThemeColors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayAreaAppeared(@NonNull DisplayAreaInfo displayAreaInfo,
|
||||
@NonNull SurfaceControl leash) {
|
||||
mParentLeash = leash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DisplayAreaAppearedInfo> registerOrganizer(int displayAreaFeature) {
|
||||
final List<DisplayAreaAppearedInfo> displayAreaInfos;
|
||||
displayAreaInfos = super.registerOrganizer(displayAreaFeature);
|
||||
for (int i = 0; i < displayAreaInfos.size(); i++) {
|
||||
final DisplayAreaAppearedInfo info = displayAreaInfos.get(i);
|
||||
onDisplayAreaAppeared(info.getDisplayAreaInfo(), info.getLeash());
|
||||
}
|
||||
return displayAreaInfos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterOrganizer() {
|
||||
super.unregisterOrganizer();
|
||||
removeBackgroundPanelLayer();
|
||||
mParentLeash = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationUpdate(SurfaceControl.Transaction tx, float xPos, float yPos) {
|
||||
final int yTopPos = (mStableInsets.top - mBkgBounds.height()) + Math.round(yPos);
|
||||
tx.setPosition(mBackgroundSurface, 0, yTopPos);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@VisibleForTesting
|
||||
boolean isRegistered() {
|
||||
return mParentLeash != null;
|
||||
}
|
||||
|
||||
void createBackgroundSurface() {
|
||||
mBackgroundSurface = new SurfaceControl.Builder(mSurfaceSession)
|
||||
.setBufferSize(mBkgBounds.width(), mBkgBounds.height())
|
||||
.setColorLayer()
|
||||
.setFormat(PixelFormat.RGB_888)
|
||||
.setOpaque(true)
|
||||
.setName("one-handed-background-panel")
|
||||
.setCallsite("OneHandedBackgroundPanelOrganizer")
|
||||
.build();
|
||||
|
||||
// TODO(185890335) Avoid Dimming for mid-range luminance wallpapers flash.
|
||||
mAlphaAnimator = ValueAnimator.ofFloat(1.0f, 0.0f);
|
||||
mAlphaAnimator.setInterpolator(new LinearInterpolator());
|
||||
mAlphaAnimator.setDuration(ALPHA_ANIMATION_DURATION);
|
||||
mAlphaAnimator.addUpdateListener(
|
||||
animator -> detachBackgroundFromParent(animator));
|
||||
}
|
||||
|
||||
void detachBackgroundFromParent(ValueAnimator animator) {
|
||||
if (mBackgroundSurface == null || mParentLeash == null) {
|
||||
return;
|
||||
}
|
||||
// TODO(185890335) Avoid Dimming for mid-range luminance wallpapers flash.
|
||||
final float currentValue = (float) animator.getAnimatedValue();
|
||||
final SurfaceControl.Transaction tx = mTransactionFactory.getTransaction();
|
||||
if (currentValue == 0.0f) {
|
||||
tx.reparent(mBackgroundSurface, null).apply();
|
||||
} else {
|
||||
tx.setAlpha(mBackgroundSurface, (float) animator.getAnimatedValue()).apply();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when onDisplayAdded() or onDisplayRemoved() callback.
|
||||
*
|
||||
* @param displayLayout The latest {@link DisplayLayout} representing current displayId
|
||||
*/
|
||||
public void onDisplayChanged(DisplayLayout displayLayout) {
|
||||
mStableInsets = displayLayout.stableInsets();
|
||||
// Ensure the mBkgBounds is portrait, due to OHM only support on portrait
|
||||
if (displayLayout.height() > displayLayout.width()) {
|
||||
mBkgBounds = new Rect(0, 0, displayLayout.width(),
|
||||
Math.round(displayLayout.height() * mTranslationFraction) + mStableInsets.top);
|
||||
} else {
|
||||
mBkgBounds = new Rect(0, 0, displayLayout.height(),
|
||||
Math.round(displayLayout.width() * mTranslationFraction) + mStableInsets.top);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void onStart() {
|
||||
if (mBackgroundSurface == null) {
|
||||
createBackgroundSurface();
|
||||
}
|
||||
showBackgroundPanelLayer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when transition finished.
|
||||
*/
|
||||
public void onStopFinished() {
|
||||
if (mAlphaAnimator == null) {
|
||||
return;
|
||||
}
|
||||
mAlphaAnimator.start();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void showBackgroundPanelLayer() {
|
||||
if (mParentLeash == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mBackgroundSurface == null) {
|
||||
createBackgroundSurface();
|
||||
}
|
||||
|
||||
// TODO(185890335) Avoid Dimming for mid-range luminance wallpapers flash.
|
||||
if (mAlphaAnimator.isRunning()) {
|
||||
mAlphaAnimator.end();
|
||||
}
|
||||
|
||||
mTransactionFactory.getTransaction()
|
||||
.reparent(mBackgroundSurface, mParentLeash)
|
||||
.setAlpha(mBackgroundSurface, 1.0f)
|
||||
.setLayer(mBackgroundSurface, -1 /* at bottom-most layer */)
|
||||
.setColor(mBackgroundSurface, mThemeColor)
|
||||
.show(mBackgroundSurface)
|
||||
.apply();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void removeBackgroundPanelLayer() {
|
||||
if (mBackgroundSurface == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
mTransactionFactory.getTransaction()
|
||||
.remove(mBackgroundSurface)
|
||||
.apply();
|
||||
mBackgroundSurface = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* onConfigurationChanged events for updating tutorial text.
|
||||
*/
|
||||
public void onConfigurationChanged() {
|
||||
updateThemeColors();
|
||||
|
||||
if (mCurrentState != STATE_ACTIVE) {
|
||||
return;
|
||||
}
|
||||
showBackgroundPanelLayer();
|
||||
}
|
||||
|
||||
private void updateThemeColors() {
|
||||
final Context themedContext = new ContextThemeWrapper(mContext,
|
||||
com.android.internal.R.style.Theme_DeviceDefault_DayNight);
|
||||
final int themeColor = themedContext.getColor(
|
||||
R.color.one_handed_tutorial_background_color);
|
||||
mThemeColor = new float[]{
|
||||
adjustColor(Color.red(themeColor)),
|
||||
adjustColor(Color.green(themeColor)),
|
||||
adjustColor(Color.blue(themeColor))};
|
||||
}
|
||||
|
||||
private float adjustColor(int origColor) {
|
||||
return Math.max(origColor - THEME_COLOR_OFFSET, 0) / 255.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateChanged(int newState) {
|
||||
mCurrentState = newState;
|
||||
}
|
||||
|
||||
void dump(@NonNull PrintWriter pw) {
|
||||
final String innerPrefix = " ";
|
||||
pw.println(TAG);
|
||||
pw.print(innerPrefix + "mBackgroundSurface=");
|
||||
pw.println(mBackgroundSurface);
|
||||
pw.print(innerPrefix + "mBkgBounds=");
|
||||
pw.println(mBkgBounds);
|
||||
pw.print(innerPrefix + "mThemeColor=");
|
||||
pw.println(mThemeColor);
|
||||
pw.print(innerPrefix + "mTranslationFraction=");
|
||||
pw.println(mTranslationFraction);
|
||||
}
|
||||
}
|
||||
@@ -99,7 +99,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
|
||||
|
||||
private OneHandedEventCallback mEventCallback;
|
||||
private OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer;
|
||||
private OneHandedBackgroundPanelOrganizer mBackgroundPanelOrganizer;
|
||||
private OneHandedUiEventLogger mOneHandedUiEventLogger;
|
||||
|
||||
private final DisplayController.OnDisplaysChangedListener mDisplaysChangedListener =
|
||||
@@ -163,7 +162,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
|
||||
public void onStopFinished(Rect bounds) {
|
||||
mState.setState(STATE_NONE);
|
||||
notifyShortcutStateChanged(STATE_NONE);
|
||||
mBackgroundPanelOrganizer.onStopFinished();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -201,32 +199,28 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
|
||||
OneHandedAccessibilityUtil accessibilityUtil = new OneHandedAccessibilityUtil(context);
|
||||
OneHandedTimeoutHandler timeoutHandler = new OneHandedTimeoutHandler(mainExecutor);
|
||||
OneHandedState oneHandedState = new OneHandedState();
|
||||
BackgroundWindowManager backgroundWindowManager = new BackgroundWindowManager(context);
|
||||
OneHandedTutorialHandler tutorialHandler = new OneHandedTutorialHandler(context,
|
||||
settingsUtil, windowManager);
|
||||
settingsUtil, windowManager, backgroundWindowManager);
|
||||
OneHandedAnimationController animationController =
|
||||
new OneHandedAnimationController(context);
|
||||
OneHandedTouchHandler touchHandler = new OneHandedTouchHandler(timeoutHandler,
|
||||
mainExecutor);
|
||||
OneHandedBackgroundPanelOrganizer oneHandedBackgroundPanelOrganizer =
|
||||
new OneHandedBackgroundPanelOrganizer(context, displayLayout, settingsUtil,
|
||||
mainExecutor);
|
||||
OneHandedDisplayAreaOrganizer organizer = new OneHandedDisplayAreaOrganizer(
|
||||
context, displayLayout, settingsUtil, animationController, tutorialHandler,
|
||||
oneHandedBackgroundPanelOrganizer, jankMonitor, mainExecutor);
|
||||
jankMonitor, mainExecutor);
|
||||
OneHandedUiEventLogger oneHandedUiEventsLogger = new OneHandedUiEventLogger(uiEventLogger);
|
||||
IOverlayManager overlayManager = IOverlayManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.OVERLAY_SERVICE));
|
||||
return new OneHandedController(context, displayController,
|
||||
oneHandedBackgroundPanelOrganizer, organizer, touchHandler, tutorialHandler,
|
||||
settingsUtil, accessibilityUtil, timeoutHandler, oneHandedState, jankMonitor,
|
||||
oneHandedUiEventsLogger, overlayManager, taskStackListener, mainExecutor,
|
||||
mainHandler);
|
||||
return new OneHandedController(context, displayController, organizer, touchHandler,
|
||||
tutorialHandler, settingsUtil, accessibilityUtil, timeoutHandler, oneHandedState,
|
||||
jankMonitor, oneHandedUiEventsLogger, overlayManager, taskStackListener,
|
||||
mainExecutor, mainHandler);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
OneHandedController(Context context,
|
||||
DisplayController displayController,
|
||||
OneHandedBackgroundPanelOrganizer backgroundPanelOrganizer,
|
||||
OneHandedDisplayAreaOrganizer displayAreaOrganizer,
|
||||
OneHandedTouchHandler touchHandler,
|
||||
OneHandedTutorialHandler tutorialHandler,
|
||||
@@ -243,7 +237,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
|
||||
mContext = context;
|
||||
mOneHandedSettingsUtil = settingsUtil;
|
||||
mOneHandedAccessibilityUtil = oneHandedAccessibilityUtil;
|
||||
mBackgroundPanelOrganizer = backgroundPanelOrganizer;
|
||||
mDisplayAreaOrganizer = displayAreaOrganizer;
|
||||
mDisplayController = displayController;
|
||||
mTouchHandler = touchHandler;
|
||||
@@ -286,7 +279,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
|
||||
mAccessibilityManager.addAccessibilityStateChangeListener(
|
||||
mAccessibilityStateChangeListener);
|
||||
|
||||
mState.addSListeners(mBackgroundPanelOrganizer);
|
||||
mState.addSListeners(mTutorialHandler);
|
||||
}
|
||||
|
||||
@@ -368,7 +360,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
|
||||
mDisplayAreaOrganizer.getDisplayLayout().height() * mOffSetFraction);
|
||||
mOneHandedAccessibilityUtil.announcementForScreenReader(
|
||||
mOneHandedAccessibilityUtil.getOneHandedStartDescription());
|
||||
mBackgroundPanelOrganizer.onStart();
|
||||
mDisplayAreaOrganizer.scheduleOffset(0, yOffSet);
|
||||
mTimeoutHandler.resetTimer();
|
||||
mOneHandedUiEventLogger.writeEvent(
|
||||
@@ -461,7 +452,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
|
||||
}
|
||||
mDisplayAreaOrganizer.setDisplayLayout(newDisplayLayout);
|
||||
mTutorialHandler.onDisplayChanged(newDisplayLayout);
|
||||
mBackgroundPanelOrganizer.onDisplayChanged(newDisplayLayout);
|
||||
}
|
||||
|
||||
private ContentObserver getObserver(Runnable onChangeRunnable) {
|
||||
@@ -585,7 +575,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
|
||||
|
||||
if (!mIsOneHandedEnabled) {
|
||||
mDisplayAreaOrganizer.unregisterOrganizer();
|
||||
mBackgroundPanelOrganizer.unregisterOrganizer();
|
||||
// Do NOT register + unRegister DA in the same call
|
||||
return;
|
||||
}
|
||||
@@ -594,11 +583,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
|
||||
mDisplayAreaOrganizer.registerOrganizer(
|
||||
OneHandedDisplayAreaOrganizer.FEATURE_ONE_HANDED);
|
||||
}
|
||||
|
||||
if (!mBackgroundPanelOrganizer.isRegistered()) {
|
||||
mBackgroundPanelOrganizer.registerOrganizer(
|
||||
OneHandedBackgroundPanelOrganizer.FEATURE_ONE_HANDED_BACKGROUND_PANEL);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -613,13 +597,12 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
|
||||
}
|
||||
|
||||
private void onConfigChanged(Configuration newConfig) {
|
||||
if (mTutorialHandler == null || mBackgroundPanelOrganizer == null) {
|
||||
if (mTutorialHandler == null) {
|
||||
return;
|
||||
}
|
||||
if (!mIsOneHandedEnabled || newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
return;
|
||||
}
|
||||
mBackgroundPanelOrganizer.onConfigurationChanged();
|
||||
mTutorialHandler.onConfigurationChanged();
|
||||
}
|
||||
|
||||
@@ -650,10 +633,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
|
||||
pw.print(innerPrefix + "mIsSwipeToNotificationEnabled=");
|
||||
pw.println(mIsSwipeToNotificationEnabled);
|
||||
|
||||
if (mBackgroundPanelOrganizer != null) {
|
||||
mBackgroundPanelOrganizer.dump(pw);
|
||||
}
|
||||
|
||||
if (mDisplayAreaOrganizer != null) {
|
||||
mDisplayAreaOrganizer.dump(pw);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
mSurfaceControlTransactionFactory;
|
||||
private OneHandedTutorialHandler mTutorialHandler;
|
||||
private List<OneHandedTransitionCallback> mTransitionCallbacks = new ArrayList<>();
|
||||
private OneHandedBackgroundPanelOrganizer mBackgroundPanelOrganizer;
|
||||
|
||||
@VisibleForTesting
|
||||
OneHandedAnimationCallback mOneHandedAnimationCallback =
|
||||
@@ -135,7 +134,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
OneHandedSettingsUtil oneHandedSettingsUtil,
|
||||
OneHandedAnimationController animationController,
|
||||
OneHandedTutorialHandler tutorialHandler,
|
||||
OneHandedBackgroundPanelOrganizer oneHandedBackgroundGradientOrganizer,
|
||||
InteractionJankMonitor jankMonitor,
|
||||
ShellExecutor mainExecutor) {
|
||||
super(mainExecutor);
|
||||
@@ -150,7 +148,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
SystemProperties.getInt(ONE_HANDED_MODE_TRANSLATE_ANIMATION_DURATION,
|
||||
animationDurationConfig);
|
||||
mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
|
||||
mBackgroundPanelOrganizer = oneHandedBackgroundGradientOrganizer;
|
||||
mTutorialHandler = tutorialHandler;
|
||||
}
|
||||
|
||||
@@ -258,7 +255,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
|
||||
animator.setTransitionDirection(direction)
|
||||
.addOneHandedAnimationCallback(mOneHandedAnimationCallback)
|
||||
.addOneHandedAnimationCallback(mTutorialHandler)
|
||||
.addOneHandedAnimationCallback(mBackgroundPanelOrganizer)
|
||||
.setDuration(durationMs)
|
||||
.start();
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ import android.content.res.ColorStateList;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.os.SystemProperties;
|
||||
import android.view.ContextThemeWrapper;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -65,6 +64,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
|
||||
private final float mTutorialHeightRatio;
|
||||
private final WindowManager mWindowManager;
|
||||
private final BackgroundWindowManager mBackgroundWindowManager;
|
||||
|
||||
private @OneHandedState.State int mCurrentState;
|
||||
private int mTutorialAreaHeight;
|
||||
@@ -79,9 +79,10 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
private int mAlphaAnimationDurationMs;
|
||||
|
||||
public OneHandedTutorialHandler(Context context, OneHandedSettingsUtil settingsUtil,
|
||||
WindowManager windowManager) {
|
||||
WindowManager windowManager, BackgroundWindowManager backgroundWindowManager) {
|
||||
mContext = context;
|
||||
mWindowManager = windowManager;
|
||||
mBackgroundWindowManager = backgroundWindowManager;
|
||||
mTutorialHeightRatio = settingsUtil.getTranslationFraction(context);
|
||||
mAlphaAnimationDurationMs = settingsUtil.getTransitionDuration(context);
|
||||
}
|
||||
@@ -109,9 +110,20 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
mAlphaAnimator.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartFinished(Rect bounds) {
|
||||
fillBackgroundColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopFinished(Rect bounds) {
|
||||
removeBackgroundSurface();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateChanged(int newState) {
|
||||
mCurrentState = newState;
|
||||
mBackgroundWindowManager.onStateChanged(newState);
|
||||
switch (newState) {
|
||||
case STATE_ENTERING:
|
||||
createViewAndAttachToWindow(mContext);
|
||||
@@ -126,7 +138,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
case STATE_NONE:
|
||||
checkTransitionEnd();
|
||||
removeTutorialFromWindowManager();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -146,6 +157,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
}
|
||||
mTutorialAreaHeight = Math.round(mDisplayBounds.height() * mTutorialHeightRatio);
|
||||
mAlphaTransitionStart = mTutorialAreaHeight * START_TRANSITION_FRACTION;
|
||||
mBackgroundWindowManager.onDisplayChanged(displayLayout);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -169,6 +181,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
private void attachTargetToWindow() {
|
||||
try {
|
||||
mWindowManager.addView(mTargetViewContainer, getTutorialTargetLayoutParams());
|
||||
mBackgroundWindowManager.showBackgroundLayer();
|
||||
} catch (IllegalStateException e) {
|
||||
// This shouldn't happen, but if the target is already added, just update its
|
||||
// layout params.
|
||||
@@ -186,6 +199,11 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
mTargetViewContainer = null;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void removeBackgroundSurface() {
|
||||
mBackgroundWindowManager.removeBackgroundLayer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns layout params for the dismiss target, using the latest display metrics.
|
||||
*/
|
||||
@@ -213,9 +231,12 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
* onConfigurationChanged events for updating tutorial text.
|
||||
*/
|
||||
public void onConfigurationChanged() {
|
||||
mBackgroundWindowManager.onConfigurationChanged();
|
||||
|
||||
removeTutorialFromWindowManager();
|
||||
if (mCurrentState == STATE_ENTERING || mCurrentState == STATE_ACTIVE) {
|
||||
createViewAndAttachToWindow(mContext);
|
||||
fillBackgroundColor();
|
||||
updateThemeColor();
|
||||
checkTransitionEnd();
|
||||
}
|
||||
@@ -247,6 +268,14 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
tutorialDesc.setTextColor(themedTextColorSecondary);
|
||||
}
|
||||
|
||||
private void fillBackgroundColor() {
|
||||
if (mTargetViewContainer == null || mBackgroundWindowManager == null) {
|
||||
return;
|
||||
}
|
||||
mTargetViewContainer.setBackgroundColor(
|
||||
mBackgroundWindowManager.getThemeColorForBackground());
|
||||
}
|
||||
|
||||
private void setupAlphaTransition(boolean isEntering) {
|
||||
final float start = isEntering ? 0.0f : 1.0f;
|
||||
final float end = isEntering ? 1.0f : 0.0f;
|
||||
@@ -282,5 +311,9 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
pw.println(mAlphaTransitionStart);
|
||||
pw.print(innerPrefix + "mAlphaAnimationDurationMs=");
|
||||
pw.println(mAlphaAnimationDurationMs);
|
||||
|
||||
if (mBackgroundWindowManager != null) {
|
||||
mBackgroundWindowManager.dump(pw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Copyright (C) 2022 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.wm.shell.onehanded;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.testing.TestableLooper;
|
||||
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.wm.shell.ShellTestCase;
|
||||
import com.android.wm.shell.common.DisplayLayout;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
/** Tests for {@link BackgroundWindowManager} */
|
||||
@SmallTest
|
||||
@TestableLooper.RunWithLooper(setAsMainLooper = true)
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BackgroundWindowManagerTest extends ShellTestCase {
|
||||
private BackgroundWindowManager mBackgroundWindowManager;
|
||||
@Mock
|
||||
private DisplayLayout mMockDisplayLayout;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mBackgroundWindowManager = new BackgroundWindowManager(mContext);
|
||||
mBackgroundWindowManager.onDisplayChanged(mMockDisplayLayout);
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void testInitRelease() {
|
||||
mBackgroundWindowManager.initView();
|
||||
assertThat(mBackgroundWindowManager.getSurfaceControl()).isNotNull();
|
||||
|
||||
mBackgroundWindowManager.removeBackgroundLayer();
|
||||
assertThat(mBackgroundWindowManager.getSurfaceControl()).isNull();
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.wm.shell.onehanded;
|
||||
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED_BACKGROUND_PANEL;
|
||||
|
||||
import static com.android.wm.shell.onehanded.OneHandedState.STATE_ACTIVE;
|
||||
import static com.android.wm.shell.onehanded.OneHandedState.STATE_NONE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.view.Display;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.DisplayAreaInfo;
|
||||
import android.window.IWindowContainerToken;
|
||||
import android.window.WindowContainerToken;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
import com.android.wm.shell.common.DisplayLayout;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
public class OneHandedBackgroundPanelOrganizerTest extends OneHandedTestCase {
|
||||
private DisplayAreaInfo mDisplayAreaInfo;
|
||||
private Display mDisplay;
|
||||
private DisplayLayout mDisplayLayout;
|
||||
private OneHandedBackgroundPanelOrganizer mSpiedBackgroundPanelOrganizer;
|
||||
private WindowContainerToken mToken;
|
||||
private SurfaceControl mLeash;
|
||||
|
||||
@Mock
|
||||
IWindowContainerToken mMockRealToken;
|
||||
@Mock
|
||||
DisplayController mMockDisplayController;
|
||||
@Mock
|
||||
OneHandedSettingsUtil mMockSettingsUtil;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mToken = new WindowContainerToken(mMockRealToken);
|
||||
mLeash = new SurfaceControl();
|
||||
mDisplay = mContext.getDisplay();
|
||||
mDisplayLayout = new DisplayLayout(mContext, mDisplay);
|
||||
when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
|
||||
mDisplayAreaInfo = new DisplayAreaInfo(mToken, DEFAULT_DISPLAY,
|
||||
FEATURE_ONE_HANDED_BACKGROUND_PANEL);
|
||||
|
||||
mSpiedBackgroundPanelOrganizer = spy(
|
||||
new OneHandedBackgroundPanelOrganizer(mContext, mDisplayLayout, mMockSettingsUtil,
|
||||
Runnable::run));
|
||||
mSpiedBackgroundPanelOrganizer.onDisplayChanged(mDisplayLayout);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnDisplayAreaAppeared() {
|
||||
mSpiedBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
|
||||
|
||||
assertThat(mSpiedBackgroundPanelOrganizer.isRegistered()).isTrue();
|
||||
verify(mSpiedBackgroundPanelOrganizer, never()).showBackgroundPanelLayer();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowBackgroundLayer() {
|
||||
mSpiedBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, null);
|
||||
mSpiedBackgroundPanelOrganizer.onStart();
|
||||
|
||||
verify(mSpiedBackgroundPanelOrganizer).showBackgroundPanelLayer();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveBackgroundLayer() {
|
||||
mSpiedBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);
|
||||
|
||||
assertThat(mSpiedBackgroundPanelOrganizer.isRegistered()).isNotNull();
|
||||
|
||||
reset(mSpiedBackgroundPanelOrganizer);
|
||||
mSpiedBackgroundPanelOrganizer.removeBackgroundPanelLayer();
|
||||
|
||||
assertThat(mSpiedBackgroundPanelOrganizer.mBackgroundSurface).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStateNone_onConfigurationChanged() {
|
||||
mSpiedBackgroundPanelOrganizer.onStateChanged(STATE_NONE);
|
||||
mSpiedBackgroundPanelOrganizer.onConfigurationChanged();
|
||||
|
||||
verify(mSpiedBackgroundPanelOrganizer, never()).showBackgroundPanelLayer();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStateActivate_onConfigurationChanged() {
|
||||
mSpiedBackgroundPanelOrganizer.onStateChanged(STATE_ACTIVE);
|
||||
mSpiedBackgroundPanelOrganizer.onConfigurationChanged();
|
||||
|
||||
verify(mSpiedBackgroundPanelOrganizer).showBackgroundPanelLayer();
|
||||
}
|
||||
}
|
||||
@@ -73,8 +73,6 @@ public class OneHandedControllerTest extends OneHandedTestCase {
|
||||
@Mock
|
||||
DisplayController mMockDisplayController;
|
||||
@Mock
|
||||
OneHandedBackgroundPanelOrganizer mMockBackgroundOrganizer;
|
||||
@Mock
|
||||
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
|
||||
@Mock
|
||||
OneHandedEventCallback mMockEventCallback;
|
||||
@@ -115,7 +113,6 @@ public class OneHandedControllerTest extends OneHandedTestCase {
|
||||
when(mMockDisplayController.getDisplayLayout(anyInt())).thenReturn(null);
|
||||
when(mMockDisplayAreaOrganizer.getDisplayAreaTokenMap()).thenReturn(new ArrayMap<>());
|
||||
when(mMockDisplayAreaOrganizer.isReady()).thenReturn(true);
|
||||
when(mMockBackgroundOrganizer.isRegistered()).thenReturn(true);
|
||||
when(mMockSettingsUitl.getSettingsOneHandedModeEnabled(any(), anyInt())).thenReturn(
|
||||
mDefaultEnabled);
|
||||
when(mMockSettingsUitl.getSettingsOneHandedModeTimeout(any(), anyInt())).thenReturn(
|
||||
@@ -134,7 +131,6 @@ public class OneHandedControllerTest extends OneHandedTestCase {
|
||||
mSpiedOneHandedController = spy(new OneHandedController(
|
||||
mContext,
|
||||
mMockDisplayController,
|
||||
mMockBackgroundOrganizer,
|
||||
mMockDisplayAreaOrganizer,
|
||||
mMockTouchHandler,
|
||||
mMockTutorialHandler,
|
||||
|
||||
@@ -95,8 +95,6 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
@Mock
|
||||
WindowContainerTransaction mMockWindowContainerTransaction;
|
||||
@Mock
|
||||
OneHandedBackgroundPanelOrganizer mMockBackgroundOrganizer;
|
||||
@Mock
|
||||
ShellExecutor mMockShellMainExecutor;
|
||||
@Mock
|
||||
OneHandedSettingsUtil mMockSettingsUitl;
|
||||
@@ -143,7 +141,6 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
mMockSettingsUitl,
|
||||
mMockAnimationController,
|
||||
mTutorialHandler,
|
||||
mMockBackgroundOrganizer,
|
||||
mJankMonitor,
|
||||
mMockShellMainExecutor));
|
||||
|
||||
@@ -431,7 +428,6 @@ public class OneHandedDisplayAreaOrganizerTest extends OneHandedTestCase {
|
||||
mMockSettingsUitl,
|
||||
mMockAnimationController,
|
||||
mTutorialHandler,
|
||||
mMockBackgroundOrganizer,
|
||||
mJankMonitor,
|
||||
mMockShellMainExecutor));
|
||||
|
||||
|
||||
@@ -67,8 +67,6 @@ public class OneHandedStateTest extends OneHandedTestCase {
|
||||
@Mock
|
||||
DisplayController mMockDisplayController;
|
||||
@Mock
|
||||
OneHandedBackgroundPanelOrganizer mMockBackgroundOrganizer;
|
||||
@Mock
|
||||
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
|
||||
@Mock
|
||||
OneHandedTouchHandler mMockTouchHandler;
|
||||
@@ -105,7 +103,6 @@ public class OneHandedStateTest extends OneHandedTestCase {
|
||||
|
||||
when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
|
||||
when(mMockDisplayAreaOrganizer.getDisplayAreaTokenMap()).thenReturn(new ArrayMap<>());
|
||||
when(mMockBackgroundOrganizer.isRegistered()).thenReturn(true);
|
||||
when(mMockSettingsUitl.getSettingsOneHandedModeEnabled(any(), anyInt())).thenReturn(
|
||||
mDefaultEnabled);
|
||||
when(mMockSettingsUitl.getSettingsOneHandedModeTimeout(any(), anyInt())).thenReturn(
|
||||
@@ -123,7 +120,6 @@ public class OneHandedStateTest extends OneHandedTestCase {
|
||||
mSpiedOneHandedController = spy(new OneHandedController(
|
||||
mContext,
|
||||
mMockDisplayController,
|
||||
mMockBackgroundOrganizer,
|
||||
mMockDisplayAreaOrganizer,
|
||||
mMockTouchHandler,
|
||||
mMockTutorialHandler,
|
||||
|
||||
@@ -56,6 +56,8 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
|
||||
OneHandedSettingsUtil mMockSettingsUtil;
|
||||
@Mock
|
||||
WindowManager mMockWindowManager;
|
||||
@Mock
|
||||
BackgroundWindowManager mMockBackgroundWindowManager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -63,10 +65,11 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
|
||||
when(mMockSettingsUtil.getTutorialShownCounts(any(), anyInt())).thenReturn(0);
|
||||
|
||||
mDisplay = mContext.getDisplay();
|
||||
mDisplayLayout = new DisplayLayout(mContext, mDisplay);
|
||||
mDisplayLayout = new DisplayLayout(getTestContext().getApplicationContext(), mDisplay);
|
||||
mSpiedTransitionState = spy(new OneHandedState());
|
||||
mSpiedTutorialHandler = spy(
|
||||
new OneHandedTutorialHandler(mContext, mMockSettingsUtil, mMockWindowManager));
|
||||
new OneHandedTutorialHandler(mContext, mMockSettingsUtil, mMockWindowManager,
|
||||
mMockBackgroundWindowManager));
|
||||
mTimeoutHandler = new OneHandedTimeoutHandler(mMockShellMainExecutor);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,13 +24,11 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_FULLSCREEN_MAGNIFICATION;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_HIDE_DISPLAY_CUTOUT;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_IME_PLACEHOLDER;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED_BACKGROUND_PANEL;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;
|
||||
|
||||
import static com.android.server.wm.DisplayAreaPolicyBuilder.Feature;
|
||||
@@ -134,11 +132,6 @@ public abstract class DisplayAreaPolicy {
|
||||
.except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL, TYPE_STATUS_BAR,
|
||||
TYPE_NOTIFICATION_SHADE)
|
||||
.build())
|
||||
.addFeature(new Feature.Builder(wmService.mPolicy,
|
||||
"OneHandedBackgroundPanel",
|
||||
FEATURE_ONE_HANDED_BACKGROUND_PANEL)
|
||||
.upTo(TYPE_WALLPAPER)
|
||||
.build())
|
||||
.addFeature(new Feature.Builder(wmService.mPolicy, "OneHanded",
|
||||
FEATURE_ONE_HANDED)
|
||||
.all()
|
||||
|
||||
@@ -30,7 +30,6 @@ import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_FULLSCREEN_MAGNIFICATION;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_IME_PLACEHOLDER;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED_BACKGROUND_PANEL;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
|
||||
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_LAST;
|
||||
@@ -196,25 +195,6 @@ public class DisplayAreaPolicyBuilderTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilder_defaultPolicy_hasOneHandedBackgroundFeature() {
|
||||
final DisplayAreaPolicy.Provider defaultProvider = DisplayAreaPolicy.Provider.fromResources(
|
||||
resourcesWithProvider(""));
|
||||
final DisplayAreaPolicyBuilder.Result defaultPolicy =
|
||||
(DisplayAreaPolicyBuilder.Result) defaultProvider.instantiate(mWms, mDisplayContent,
|
||||
mRoot, mImeContainer);
|
||||
if (mDisplayContent.isDefaultDisplay) {
|
||||
final List<Feature> features = defaultPolicy.getFeatures();
|
||||
boolean hasOneHandedBackgroundFeature = false;
|
||||
for (Feature feature : features) {
|
||||
hasOneHandedBackgroundFeature |=
|
||||
feature.getId() == FEATURE_ONE_HANDED_BACKGROUND_PANEL;
|
||||
}
|
||||
|
||||
assertThat(hasOneHandedBackgroundFeature).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuilder_defaultPolicy_hasWindowedMagnificationFeature() {
|
||||
final DisplayAreaPolicy.Provider defaultProvider = DisplayAreaPolicy.Provider.fromResources(
|
||||
|
||||
Reference in New Issue
Block a user