Merge "Move floating rotation button handling to Launcher" into sc-v2-dev am: 1aef5f62a1
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16101761 Change-Id: Idfcc8a6f075aecb1c54ecae4dbb26f4cb6b83039
This commit is contained in:
@@ -81,7 +81,6 @@
|
|||||||
<dimen name="fab_margin">24dp</dimen>
|
<dimen name="fab_margin">24dp</dimen>
|
||||||
|
|
||||||
<dimen name="navigation_key_width">128dp</dimen>
|
<dimen name="navigation_key_width">128dp</dimen>
|
||||||
<dimen name="navigation_key_padding">25dp</dimen>
|
|
||||||
|
|
||||||
<!-- Keyboard shortcuts helper -->
|
<!-- Keyboard shortcuts helper -->
|
||||||
<dimen name="ksh_layout_width">488dp</dimen>
|
<dimen name="ksh_layout_width">488dp</dimen>
|
||||||
|
|||||||
@@ -21,11 +21,4 @@
|
|||||||
<dimen name="navigation_side_padding">@dimen/button_size</dimen>
|
<dimen name="navigation_side_padding">@dimen/button_size</dimen>
|
||||||
<dimen name="navigation_key_width">@dimen/button_size</dimen>
|
<dimen name="navigation_key_width">@dimen/button_size</dimen>
|
||||||
<dimen name="navigation_extra_key_width">@dimen/button_size</dimen>
|
<dimen name="navigation_extra_key_width">@dimen/button_size</dimen>
|
||||||
|
|
||||||
<!-- The maximum width of the navigation bar ripples. -->
|
|
||||||
<dimen name="key_button_ripple_max_width">76dp</dimen>
|
|
||||||
|
|
||||||
<!-- The padding around the navigation buttons -->
|
|
||||||
<dimen name="navigation_key_padding">0dp</dimen>
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -56,11 +56,6 @@
|
|||||||
<!-- The amount by which the arrow is shifted to avoid the finger-->
|
<!-- The amount by which the arrow is shifted to avoid the finger-->
|
||||||
<dimen name="navigation_edge_finger_offset">48dp</dimen>
|
<dimen name="navigation_edge_finger_offset">48dp</dimen>
|
||||||
|
|
||||||
<dimen name="floating_rotation_button_diameter">40dp</dimen>
|
|
||||||
<dimen name="floating_rotation_button_min_margin">20dp</dimen>
|
|
||||||
<dimen name="floating_rotation_button_taskbar_left_margin">20dp</dimen>
|
|
||||||
<dimen name="floating_rotation_button_taskbar_bottom_margin">10dp</dimen>
|
|
||||||
|
|
||||||
<!-- Height of notification icons in the status bar -->
|
<!-- Height of notification icons in the status bar -->
|
||||||
<dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
|
<dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
|
||||||
|
|
||||||
@@ -361,8 +356,6 @@
|
|||||||
<!-- The width/height of the icon of a navigation button -->
|
<!-- The width/height of the icon of a navigation button -->
|
||||||
<dimen name="navigation_icon_size">32dp</dimen>
|
<dimen name="navigation_icon_size">32dp</dimen>
|
||||||
|
|
||||||
<dimen name="navigation_key_padding">0dp</dimen>
|
|
||||||
|
|
||||||
<!-- The width of the view containing the menu/ime navigation bar icons -->
|
<!-- The width of the view containing the menu/ime navigation bar icons -->
|
||||||
<dimen name="navigation_extra_key_width">36dp</dimen>
|
<dimen name="navigation_extra_key_width">36dp</dimen>
|
||||||
|
|
||||||
@@ -974,9 +967,6 @@
|
|||||||
|
|
||||||
<dimen name="signal_indicator_to_icon_frame_spacing">3dp</dimen>
|
<dimen name="signal_indicator_to_icon_frame_spacing">3dp</dimen>
|
||||||
|
|
||||||
<!-- The maximum width of the navigation bar ripples. -->
|
|
||||||
<dimen name="key_button_ripple_max_width">95dp</dimen>
|
|
||||||
|
|
||||||
<!-- Inset shadow for FakeShadowDrawable. It is used to avoid gaps between the card
|
<!-- Inset shadow for FakeShadowDrawable. It is used to avoid gaps between the card
|
||||||
and the shadow. -->
|
and the shadow. -->
|
||||||
<dimen name="fake_shadow_inset">1dp</dimen>
|
<dimen name="fake_shadow_inset">1dp</dimen>
|
||||||
@@ -1166,7 +1156,6 @@
|
|||||||
|
|
||||||
<!-- The absolute side margins of quick settings -->
|
<!-- The absolute side margins of quick settings -->
|
||||||
<dimen name="quick_settings_bottom_margin_media">8dp</dimen>
|
<dimen name="quick_settings_bottom_margin_media">8dp</dimen>
|
||||||
<dimen name="rounded_corner_content_padding">0dp</dimen>
|
|
||||||
<dimen name="nav_content_padding">0dp</dimen>
|
<dimen name="nav_content_padding">0dp</dimen>
|
||||||
<dimen name="nav_quick_scrub_track_edge_padding">24dp</dimen>
|
<dimen name="nav_quick_scrub_track_edge_padding">24dp</dimen>
|
||||||
<dimen name="nav_quick_scrub_track_thickness">10dp</dimen>
|
<dimen name="nav_quick_scrub_track_thickness">10dp</dimen>
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ android_library {
|
|||||||
":wm_shell-aidls",
|
":wm_shell-aidls",
|
||||||
":wm_shell_util-sources",
|
":wm_shell_util-sources",
|
||||||
],
|
],
|
||||||
|
resource_dirs: [
|
||||||
|
"res",
|
||||||
|
],
|
||||||
static_libs: [
|
static_libs: [
|
||||||
"PluginCoreLib",
|
"PluginCoreLib",
|
||||||
"androidx.dynamicanimation_dynamicanimation",
|
"androidx.dynamicanimation_dynamicanimation",
|
||||||
|
|||||||
@@ -18,12 +18,10 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
>
|
>
|
||||||
|
<com.android.systemui.shared.rotation.FloatingRotationButtonView
|
||||||
<com.android.systemui.navigationbar.buttons.KeyButtonView
|
|
||||||
android:id="@+id/rotate_suggestion"
|
android:id="@+id/rotate_suggestion"
|
||||||
android:layout_width="@dimen/floating_rotation_button_diameter"
|
android:layout_width="@dimen/floating_rotation_button_diameter"
|
||||||
android:layout_height="@dimen/floating_rotation_button_diameter"
|
android:layout_height="@dimen/floating_rotation_button_diameter"
|
||||||
android:contentDescription="@string/accessibility_rotate_button"
|
|
||||||
android:paddingStart="@dimen/navigation_key_padding"
|
android:paddingStart="@dimen/navigation_key_padding"
|
||||||
android:paddingEnd="@dimen/navigation_key_padding"
|
android:paddingEnd="@dimen/navigation_key_padding"
|
||||||
android:layout_gravity="bottom|left"
|
android:layout_gravity="bottom|left"
|
||||||
19
packages/SystemUI/shared/res/values-sw600dp/dimens.xml
Normal file
19
packages/SystemUI/shared/res/values-sw600dp/dimens.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
* Copyright (c) 2021, 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.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<resources>
|
||||||
|
<dimen name="navigation_key_padding">25dp</dimen>
|
||||||
|
</resources>
|
||||||
23
packages/SystemUI/shared/res/values-sw900dp/dimens.xml
Normal file
23
packages/SystemUI/shared/res/values-sw900dp/dimens.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
* Copyright (c) 2021, 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.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<resources>
|
||||||
|
<!-- The maximum width of the navigation bar ripples. -->
|
||||||
|
<dimen name="key_button_ripple_max_width">76dp</dimen>
|
||||||
|
|
||||||
|
<!-- The padding around the navigation buttons -->
|
||||||
|
<dimen name="navigation_key_padding">0dp</dimen>
|
||||||
|
</resources>
|
||||||
30
packages/SystemUI/shared/res/values/dimens.xml
Normal file
30
packages/SystemUI/shared/res/values/dimens.xml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?><!--
|
||||||
|
* Copyright (c) 2021, 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.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
<resources>
|
||||||
|
<!-- The maximum width of the navigation bar ripples. -->
|
||||||
|
<dimen name="key_button_ripple_max_width">95dp</dimen>
|
||||||
|
|
||||||
|
<dimen name="rounded_corner_content_padding">0dp</dimen>
|
||||||
|
|
||||||
|
<dimen name="navigation_key_padding">0dp</dimen>
|
||||||
|
|
||||||
|
<!-- Floating rotation button -->
|
||||||
|
<dimen name="floating_rotation_button_diameter">40dp</dimen>
|
||||||
|
<dimen name="floating_rotation_button_min_margin">20dp</dimen>
|
||||||
|
<dimen name="floating_rotation_button_taskbar_left_margin">20dp</dimen>
|
||||||
|
<dimen name="floating_rotation_button_taskbar_bottom_margin">10dp</dimen>
|
||||||
|
</resources>
|
||||||
@@ -33,12 +33,12 @@ import android.view.RenderNodeAnimator;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewConfiguration;
|
import android.view.ViewConfiguration;
|
||||||
import android.view.animation.Interpolator;
|
import android.view.animation.Interpolator;
|
||||||
|
import android.view.animation.PathInterpolator;
|
||||||
import com.android.systemui.R;
|
|
||||||
import com.android.systemui.animation.Interpolators;
|
|
||||||
|
|
||||||
import androidx.annotation.Keep;
|
import androidx.annotation.Keep;
|
||||||
|
|
||||||
|
import com.android.systemui.shared.R;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
@@ -49,6 +49,8 @@ public class KeyButtonRipple extends Drawable {
|
|||||||
private static final float GLOW_MAX_ALPHA_DARK = 0.1f;
|
private static final float GLOW_MAX_ALPHA_DARK = 0.1f;
|
||||||
private static final int ANIMATION_DURATION_SCALE = 350;
|
private static final int ANIMATION_DURATION_SCALE = 350;
|
||||||
private static final int ANIMATION_DURATION_FADE = 450;
|
private static final int ANIMATION_DURATION_FADE = 450;
|
||||||
|
private static final Interpolator ALPHA_OUT_INTERPOLATOR =
|
||||||
|
new PathInterpolator(0f, 0f, 0.8f, 1f);
|
||||||
|
|
||||||
private Paint mRipplePaint;
|
private Paint mRipplePaint;
|
||||||
private CanvasProperty<Float> mLeftProp;
|
private CanvasProperty<Float> mLeftProp;
|
||||||
@@ -336,7 +338,7 @@ public class KeyButtonRipple extends Drawable {
|
|||||||
|
|
||||||
private void exitSoftware() {
|
private void exitSoftware() {
|
||||||
ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(this, "glowAlpha", mGlowAlpha, 0f);
|
ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(this, "glowAlpha", mGlowAlpha, 0f);
|
||||||
alphaAnimator.setInterpolator(Interpolators.ALPHA_OUT);
|
alphaAnimator.setInterpolator(ALPHA_OUT_INTERPOLATOR);
|
||||||
alphaAnimator.setDuration(ANIMATION_DURATION_FADE);
|
alphaAnimator.setDuration(ANIMATION_DURATION_FADE);
|
||||||
alphaAnimator.addListener(mAnimatorListener);
|
alphaAnimator.addListener(mAnimatorListener);
|
||||||
alphaAnimator.start();
|
alphaAnimator.start();
|
||||||
@@ -459,7 +461,7 @@ public class KeyButtonRipple extends Drawable {
|
|||||||
final RenderNodeAnimator opacityAnim = new RenderNodeAnimator(mPaintProp,
|
final RenderNodeAnimator opacityAnim = new RenderNodeAnimator(mPaintProp,
|
||||||
RenderNodeAnimator.PAINT_ALPHA, 0);
|
RenderNodeAnimator.PAINT_ALPHA, 0);
|
||||||
opacityAnim.setDuration(ANIMATION_DURATION_FADE);
|
opacityAnim.setDuration(ANIMATION_DURATION_FADE);
|
||||||
opacityAnim.setInterpolator(Interpolators.ALPHA_OUT);
|
opacityAnim.setInterpolator(ALPHA_OUT_INTERPOLATOR);
|
||||||
opacityAnim.addListener(mAnimatorListener);
|
opacityAnim.addListener(mAnimatorListener);
|
||||||
opacityAnim.addListener(mExitHwTraceAnimator);
|
opacityAnim.addListener(mExitHwTraceAnimator);
|
||||||
opacityAnim.setTarget(mTargetView);
|
opacityAnim.setTarget(mTargetView);
|
||||||
@@ -14,12 +14,14 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.systemui.navigationbar.gestural;
|
package com.android.systemui.shared.rotation;
|
||||||
|
|
||||||
|
import android.annotation.StringRes;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
|
import android.graphics.drawable.AnimatedVectorDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@@ -27,28 +29,25 @@ import android.view.WindowManager;
|
|||||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
import com.android.systemui.R;
|
import androidx.core.view.OneShotPreDrawListener;
|
||||||
import com.android.systemui.navigationbar.RotationButton;
|
|
||||||
import com.android.systemui.navigationbar.RotationButtonController;
|
import com.android.systemui.shared.R;
|
||||||
import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
|
import com.android.systemui.shared.rotation.FloatingRotationButtonPositionCalculator.Position;
|
||||||
import com.android.systemui.navigationbar.buttons.KeyButtonView;
|
|
||||||
import com.android.systemui.navigationbar.gestural.FloatingRotationButtonPositionCalculator.Position;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Containing logic for the rotation button on the physical left bottom corner of the screen.
|
* Containing logic for the rotation button on the physical left bottom corner of the screen.
|
||||||
*/
|
*/
|
||||||
public class FloatingRotationButton implements RotationButton {
|
public class FloatingRotationButton implements RotationButton {
|
||||||
|
|
||||||
private static final float BACKGROUND_ALPHA = 0.92f;
|
|
||||||
private static final int MARGIN_ANIMATION_DURATION_MILLIS = 300;
|
private static final int MARGIN_ANIMATION_DURATION_MILLIS = 300;
|
||||||
|
|
||||||
private final WindowManager mWindowManager;
|
private final WindowManager mWindowManager;
|
||||||
private final ViewGroup mKeyButtonContainer;
|
private final ViewGroup mKeyButtonContainer;
|
||||||
private final KeyButtonView mKeyButtonView;
|
private final FloatingRotationButtonView mKeyButtonView;
|
||||||
|
|
||||||
private final int mContainerSize;
|
private final int mContainerSize;
|
||||||
|
|
||||||
private KeyButtonDrawable mKeyButtonDrawable;
|
private AnimatedVectorDrawable mAnimatedDrawable;
|
||||||
private boolean mIsShowing;
|
private boolean mIsShowing;
|
||||||
private boolean mCanShow = true;
|
private boolean mCanShow = true;
|
||||||
private int mDisplayRotation;
|
private int mDisplayRotation;
|
||||||
@@ -62,12 +61,13 @@ public class FloatingRotationButton implements RotationButton {
|
|||||||
private RotationButtonUpdatesCallback mUpdatesCallback;
|
private RotationButtonUpdatesCallback mUpdatesCallback;
|
||||||
private Position mPosition;
|
private Position mPosition;
|
||||||
|
|
||||||
public FloatingRotationButton(Context context) {
|
public FloatingRotationButton(Context context, @StringRes int contentDescription) {
|
||||||
mWindowManager = context.getSystemService(WindowManager.class);
|
mWindowManager = context.getSystemService(WindowManager.class);
|
||||||
mKeyButtonContainer = (ViewGroup) LayoutInflater.from(context).inflate(
|
mKeyButtonContainer = (ViewGroup) LayoutInflater.from(context).inflate(
|
||||||
R.layout.rotate_suggestion, null);
|
R.layout.rotate_suggestion, null);
|
||||||
mKeyButtonView = mKeyButtonContainer.findViewById(R.id.rotate_suggestion);
|
mKeyButtonView = mKeyButtonContainer.findViewById(R.id.rotate_suggestion);
|
||||||
mKeyButtonView.setVisibility(View.VISIBLE);
|
mKeyButtonView.setVisibility(View.VISIBLE);
|
||||||
|
mKeyButtonView.setContentDescription(context.getString(contentDescription));
|
||||||
|
|
||||||
Resources res = context.getResources();
|
Resources res = context.getResources();
|
||||||
|
|
||||||
@@ -113,6 +113,10 @@ public class FloatingRotationButton implements RotationButton {
|
|||||||
|
|
||||||
mIsShowing = true;
|
mIsShowing = true;
|
||||||
int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||||
|
|
||||||
|
// TODO(b/200103245): add new window type that has z-index above
|
||||||
|
// TYPE_NAVIGATION_BAR_PANEL as currently it could be below the taskbar which has
|
||||||
|
// the same window type
|
||||||
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
||||||
mContainerSize,
|
mContainerSize,
|
||||||
mContainerSize,
|
mContainerSize,
|
||||||
@@ -134,14 +138,18 @@ public class FloatingRotationButton implements RotationButton {
|
|||||||
updateTranslation(mPosition, /* animate */ false);
|
updateTranslation(mPosition, /* animate */ false);
|
||||||
|
|
||||||
mWindowManager.addView(mKeyButtonContainer, lp);
|
mWindowManager.addView(mKeyButtonContainer, lp);
|
||||||
if (mKeyButtonDrawable != null && mKeyButtonDrawable.canAnimate()) {
|
if (mAnimatedDrawable != null) {
|
||||||
mKeyButtonDrawable.resetAnimation();
|
mAnimatedDrawable.reset();
|
||||||
mKeyButtonDrawable.startAnimation();
|
mAnimatedDrawable.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mUpdatesCallback != null) {
|
// Notify about visibility only after first traversal so we can properly calculate
|
||||||
mUpdatesCallback.onVisibilityChanged(true);
|
// the touch region for the button
|
||||||
}
|
OneShotPreDrawListener.add(mKeyButtonView, () -> {
|
||||||
|
if (mIsShowing && mUpdatesCallback != null) {
|
||||||
|
mUpdatesCallback.onVisibilityChanged(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -166,12 +174,10 @@ public class FloatingRotationButton implements RotationButton {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateIcon(int lightIconColor, int darkIconColor) {
|
public void updateIcon(int lightIconColor, int darkIconColor) {
|
||||||
Color ovalBackgroundColor = Color.valueOf(Color.red(darkIconColor),
|
mAnimatedDrawable = (AnimatedVectorDrawable) mKeyButtonView.getContext()
|
||||||
Color.green(darkIconColor), Color.blue(darkIconColor), BACKGROUND_ALPHA);
|
.getDrawable(mRotationButtonController.getIconResId());
|
||||||
mKeyButtonDrawable = KeyButtonDrawable.create(mRotationButtonController.getContext(),
|
mKeyButtonView.setImageDrawable(mAnimatedDrawable);
|
||||||
lightIconColor, darkIconColor, mRotationButtonController.getIconResId(),
|
mKeyButtonView.setColors(lightIconColor, darkIconColor);
|
||||||
false /* shadow */, ovalBackgroundColor);
|
|
||||||
mKeyButtonView.setImageDrawable(mKeyButtonDrawable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -185,8 +191,8 @@ public class FloatingRotationButton implements RotationButton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeyButtonDrawable getImageDrawable() {
|
public Drawable getImageDrawable() {
|
||||||
return mKeyButtonDrawable;
|
return mAnimatedDrawable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -202,6 +208,7 @@ public class FloatingRotationButton implements RotationButton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void onTaskbarStateChanged(boolean taskbarVisible, boolean taskbarStashed) {
|
public void onTaskbarStateChanged(boolean taskbarVisible, boolean taskbarStashed) {
|
||||||
mIsTaskbarVisible = taskbarVisible;
|
mIsTaskbarVisible = taskbarVisible;
|
||||||
mIsTaskbarStashed = taskbarStashed;
|
mIsTaskbarStashed = taskbarStashed;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package com.android.systemui.navigationbar.gestural
|
package com.android.systemui.shared.rotation
|
||||||
|
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.Surface
|
import android.view.Surface
|
||||||
@@ -7,7 +7,7 @@ import android.view.Surface
|
|||||||
* Calculates gravity and translation that is necessary to display
|
* Calculates gravity and translation that is necessary to display
|
||||||
* the button in the correct position based on the current state
|
* the button in the correct position based on the current state
|
||||||
*/
|
*/
|
||||||
internal class FloatingRotationButtonPositionCalculator(
|
class FloatingRotationButtonPositionCalculator(
|
||||||
private val defaultMargin: Int,
|
private val defaultMargin: Int,
|
||||||
private val taskbarMarginLeft: Int,
|
private val taskbarMarginLeft: Int,
|
||||||
private val taskbarMarginBottom: Int
|
private val taskbarMarginBottom: Int
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.systemui.shared.rotation;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.PorterDuffColorFilter;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import com.android.systemui.navigationbar.buttons.KeyButtonRipple;
|
||||||
|
|
||||||
|
public class FloatingRotationButtonView extends ImageView {
|
||||||
|
|
||||||
|
private static final float BACKGROUND_ALPHA = 0.92f;
|
||||||
|
|
||||||
|
private final KeyButtonRipple mRipple;
|
||||||
|
private final Paint mOvalBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
|
||||||
|
|
||||||
|
public FloatingRotationButtonView(Context context, AttributeSet attrs) {
|
||||||
|
this(context, attrs, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FloatingRotationButtonView(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
|
||||||
|
setClickable(true);
|
||||||
|
|
||||||
|
mRipple = new KeyButtonRipple(context, this);
|
||||||
|
setBackground(mRipple);
|
||||||
|
setWillNotDraw(false);
|
||||||
|
forceHasOverlappingRendering(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onWindowVisibilityChanged(int visibility) {
|
||||||
|
super.onWindowVisibilityChanged(visibility);
|
||||||
|
if (visibility != View.VISIBLE) {
|
||||||
|
jumpDrawablesToCurrentState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColors(int lightColor, int darkColor) {
|
||||||
|
getDrawable().setColorFilter(new PorterDuffColorFilter(lightColor, PorterDuff.Mode.SRC_IN));
|
||||||
|
|
||||||
|
final int ovalBackgroundColor = Color.valueOf(Color.red(darkColor),
|
||||||
|
Color.green(darkColor), Color.blue(darkColor), BACKGROUND_ALPHA).toArgb();
|
||||||
|
|
||||||
|
mOvalBgPaint.setColor(ovalBackgroundColor);
|
||||||
|
mRipple.setType(KeyButtonRipple.Type.OVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDarkIntensity(float darkIntensity) {
|
||||||
|
mRipple.setDarkIntensity(darkIntensity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(Canvas canvas) {
|
||||||
|
int d = Math.min(getWidth(), getHeight());
|
||||||
|
canvas.drawOval(0, 0, d, d, mOvalBgPaint);
|
||||||
|
super.draw(canvas);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.systemui.shared.rotation;
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface of a rotation button that interacts {@link RotationButtonController}.
|
||||||
|
* This interface exists because of the two different styles of rotation button in Sysui,
|
||||||
|
* one in contextual for 3 button nav and a floating rotation button for gestural.
|
||||||
|
*/
|
||||||
|
public interface RotationButton {
|
||||||
|
default void setRotationButtonController(RotationButtonController rotationButtonController) { }
|
||||||
|
default void setUpdatesCallback(RotationButtonUpdatesCallback updatesCallback) { }
|
||||||
|
|
||||||
|
default View getCurrentView() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
default boolean show() { return false; }
|
||||||
|
default boolean hide() { return false; }
|
||||||
|
default boolean isVisible() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default void setCanShowRotationButton(boolean canShow) {}
|
||||||
|
default void onTaskbarStateChanged(boolean taskbarVisible, boolean taskbarStashed) {}
|
||||||
|
default void updateIcon(int lightIconColor, int darkIconColor) { }
|
||||||
|
default void setOnClickListener(View.OnClickListener onClickListener) { }
|
||||||
|
default void setOnHoverListener(View.OnHoverListener onHoverListener) { }
|
||||||
|
default Drawable getImageDrawable() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
default void setDarkIntensity(float darkIntensity) { }
|
||||||
|
default boolean acceptRotationProposal() {
|
||||||
|
return getCurrentView() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for updates provided by a rotation button
|
||||||
|
*/
|
||||||
|
interface RotationButtonUpdatesCallback {
|
||||||
|
default void onVisibilityChanged(boolean isVisible) {};
|
||||||
|
default void onPositionChanged() {};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2020 The Android Open Source Project
|
* Copyright 2021 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -14,7 +14,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.android.systemui.navigationbar;
|
package com.android.systemui.shared.rotation;
|
||||||
|
|
||||||
|
import static android.view.Display.DEFAULT_DISPLAY;
|
||||||
|
|
||||||
import static com.android.internal.view.RotationPolicy.NATURAL_ROTATION;
|
import static com.android.internal.view.RotationPolicy.NATURAL_ROTATION;
|
||||||
|
|
||||||
@@ -23,48 +25,51 @@ import android.animation.AnimatorListenerAdapter;
|
|||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.annotation.ColorInt;
|
import android.annotation.ColorInt;
|
||||||
import android.annotation.DrawableRes;
|
import android.annotation.DrawableRes;
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.StatusBarManager;
|
import android.app.StatusBarManager;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.AnimatedVectorDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.IRotationWatcher.Stub;
|
import android.view.IRotationWatcher;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowInsetsController;
|
import android.view.WindowInsetsController;
|
||||||
import android.view.WindowInsetsController.Behavior;
|
|
||||||
import android.view.WindowManagerGlobal;
|
import android.view.WindowManagerGlobal;
|
||||||
import android.view.accessibility.AccessibilityManager;
|
import android.view.accessibility.AccessibilityManager;
|
||||||
|
import android.view.animation.Interpolator;
|
||||||
|
import android.view.animation.LinearInterpolator;
|
||||||
|
|
||||||
import com.android.internal.logging.UiEvent;
|
import com.android.internal.logging.UiEvent;
|
||||||
import com.android.internal.logging.UiEventLogger;
|
import com.android.internal.logging.UiEventLogger;
|
||||||
import com.android.internal.logging.UiEventLoggerImpl;
|
import com.android.internal.logging.UiEventLoggerImpl;
|
||||||
import com.android.systemui.Dependency;
|
import com.android.internal.view.RotationPolicy;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.shared.rotation.RotationButton.RotationButtonUpdatesCallback;
|
||||||
import com.android.systemui.animation.Interpolators;
|
|
||||||
import com.android.systemui.navigationbar.RotationButton.RotationButtonUpdatesCallback;
|
|
||||||
import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
|
|
||||||
import com.android.systemui.shared.recents.utilities.Utilities;
|
import com.android.systemui.shared.recents.utilities.Utilities;
|
||||||
import com.android.systemui.shared.recents.utilities.ViewRippler;
|
import com.android.systemui.shared.recents.utilities.ViewRippler;
|
||||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||||
import com.android.systemui.shared.system.TaskStackChangeListeners;
|
import com.android.systemui.shared.system.TaskStackChangeListeners;
|
||||||
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
|
|
||||||
import com.android.systemui.statusbar.policy.RotationLockController;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/** Contains logic that deals with showing a rotate suggestion button with animation. */
|
/**
|
||||||
|
* Contains logic that deals with showing a rotate suggestion button with animation.
|
||||||
|
*/
|
||||||
public class RotationButtonController {
|
public class RotationButtonController {
|
||||||
|
|
||||||
private static final String TAG = "StatusBar/RotationButtonController";
|
private static final String TAG = "StatusBar/RotationButtonController";
|
||||||
private static final int BUTTON_FADE_IN_OUT_DURATION_MS = 100;
|
private static final int BUTTON_FADE_IN_OUT_DURATION_MS = 100;
|
||||||
private static final int NAVBAR_HIDDEN_PENDING_ICON_TIMEOUT_MS = 20000;
|
private static final int NAVBAR_HIDDEN_PENDING_ICON_TIMEOUT_MS = 20000;
|
||||||
|
private static final Interpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
|
||||||
|
|
||||||
private static final int NUM_ACCEPTED_ROTATION_SUGGESTIONS_FOR_INTRODUCTION = 3;
|
private static final int NUM_ACCEPTED_ROTATION_SUGGESTIONS_FOR_INTRODUCTION = 3;
|
||||||
|
|
||||||
@@ -72,6 +77,7 @@ public class RotationButtonController {
|
|||||||
private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
|
private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
|
||||||
private final UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
|
private final UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
|
||||||
private final ViewRippler mViewRippler = new ViewRippler();
|
private final ViewRippler mViewRippler = new ViewRippler();
|
||||||
|
private final Supplier<Integer> mWindowRotationProvider;
|
||||||
private RotationButton mRotationButton;
|
private RotationButton mRotationButton;
|
||||||
|
|
||||||
private boolean mIsRecentsAnimationRunning;
|
private boolean mIsRecentsAnimationRunning;
|
||||||
@@ -79,17 +85,30 @@ public class RotationButtonController {
|
|||||||
private int mLastRotationSuggestion;
|
private int mLastRotationSuggestion;
|
||||||
private boolean mPendingRotationSuggestion;
|
private boolean mPendingRotationSuggestion;
|
||||||
private boolean mHoveringRotationSuggestion;
|
private boolean mHoveringRotationSuggestion;
|
||||||
private RotationLockController mRotationLockController;
|
private final AccessibilityManager mAccessibilityManager;
|
||||||
private AccessibilityManagerWrapper mAccessibilityManagerWrapper;
|
private final TaskStackListenerImpl mTaskStackListener;
|
||||||
private TaskStackListenerImpl mTaskStackListener;
|
|
||||||
private Consumer<Integer> mRotWatcherListener;
|
private Consumer<Integer> mRotWatcherListener;
|
||||||
|
|
||||||
private boolean mListenersRegistered = false;
|
private boolean mListenersRegistered = false;
|
||||||
private boolean mIsNavigationBarShowing;
|
private boolean mIsNavigationBarShowing;
|
||||||
private @Behavior int mBehavior = WindowInsetsController.BEHAVIOR_DEFAULT;
|
@SuppressLint("InlinedApi")
|
||||||
|
private @WindowInsetsController.Behavior
|
||||||
|
int mBehavior = WindowInsetsController.BEHAVIOR_DEFAULT;
|
||||||
private boolean mSkipOverrideUserLockPrefsOnce;
|
private boolean mSkipOverrideUserLockPrefsOnce;
|
||||||
private int mLightIconColor;
|
private final int mLightIconColor;
|
||||||
private int mDarkIconColor;
|
private final int mDarkIconColor;
|
||||||
private int mIconResId = R.drawable.ic_sysbar_rotate_button_ccw_start_90;
|
|
||||||
|
@DrawableRes
|
||||||
|
private final int mIconCcwStart0ResId;
|
||||||
|
@DrawableRes
|
||||||
|
private final int mIconCcwStart90ResId;
|
||||||
|
@DrawableRes
|
||||||
|
private final int mIconCwStart0ResId;
|
||||||
|
@DrawableRes
|
||||||
|
private final int mIconCwStart90ResId;
|
||||||
|
|
||||||
|
@DrawableRes
|
||||||
|
private int mIconResId;
|
||||||
|
|
||||||
private final Runnable mRemoveRotationProposal =
|
private final Runnable mRemoveRotationProposal =
|
||||||
() -> setRotateSuggestionButtonState(false /* visible */);
|
() -> setRotateSuggestionButtonState(false /* visible */);
|
||||||
@@ -97,19 +116,20 @@ public class RotationButtonController {
|
|||||||
() -> mPendingRotationSuggestion = false;
|
() -> mPendingRotationSuggestion = false;
|
||||||
private Animator mRotateHideAnimator;
|
private Animator mRotateHideAnimator;
|
||||||
|
|
||||||
private final Stub mRotationWatcher = new Stub() {
|
|
||||||
|
private final IRotationWatcher.Stub mRotationWatcher = new IRotationWatcher.Stub() {
|
||||||
@Override
|
@Override
|
||||||
public void onRotationChanged(final int rotation) throws RemoteException {
|
public void onRotationChanged(final int rotation) {
|
||||||
// We need this to be scheduled as early as possible to beat the redrawing of
|
// We need this to be scheduled as early as possible to beat the redrawing of
|
||||||
// window in response to the orientation change.
|
// window in response to the orientation change.
|
||||||
mMainThreadHandler.postAtFrontOfQueue(() -> {
|
mMainThreadHandler.postAtFrontOfQueue(() -> {
|
||||||
// If the screen rotation changes while locked, potentially update lock to flow with
|
// If the screen rotation changes while locked, potentially update lock to flow with
|
||||||
// new screen rotation and hide any showing suggestions.
|
// new screen rotation and hide any showing suggestions.
|
||||||
if (mRotationLockController.isRotationLocked()) {
|
if (isRotationLocked()) {
|
||||||
if (shouldOverrideUserLockPrefs(rotation)) {
|
if (shouldOverrideUserLockPrefs(rotation)) {
|
||||||
setRotationLockedAtAngle(rotation);
|
setRotationLockedAtAngle(rotation);
|
||||||
}
|
}
|
||||||
setRotateSuggestionButtonState(false /* visible */, true /* hideImmediately */);
|
setRotateSuggestionButtonState(false /* visible */, true /* forced */);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mRotWatcherListener != null) {
|
if (mRotWatcherListener != null) {
|
||||||
@@ -121,27 +141,39 @@ public class RotationButtonController {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if rotation suggestions disabled2 flag exists in flag
|
* Determines if rotation suggestions disabled2 flag exists in flag
|
||||||
|
*
|
||||||
* @param disable2Flags see if rotation suggestion flag exists in this flag
|
* @param disable2Flags see if rotation suggestion flag exists in this flag
|
||||||
* @return whether flag exists
|
* @return whether flag exists
|
||||||
*/
|
*/
|
||||||
static boolean hasDisable2RotateSuggestionFlag(int disable2Flags) {
|
public static boolean hasDisable2RotateSuggestionFlag(int disable2Flags) {
|
||||||
return (disable2Flags & StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS) != 0;
|
return (disable2Flags & StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RotationButtonController(Context context, @ColorInt int lightIconColor,
|
public RotationButtonController(Context context,
|
||||||
@ColorInt int darkIconColor) {
|
@ColorInt int lightIconColor, @ColorInt int darkIconColor,
|
||||||
|
@DrawableRes int iconCcwStart0ResId,
|
||||||
|
@DrawableRes int iconCcwStart90ResId,
|
||||||
|
@DrawableRes int iconCwStart0ResId,
|
||||||
|
@DrawableRes int iconCwStart90ResId,
|
||||||
|
Supplier<Integer> windowRotationProvider) {
|
||||||
|
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mLightIconColor = lightIconColor;
|
mLightIconColor = lightIconColor;
|
||||||
mDarkIconColor = darkIconColor;
|
mDarkIconColor = darkIconColor;
|
||||||
|
|
||||||
mIsNavigationBarShowing = true;
|
mIconCcwStart0ResId = iconCcwStart0ResId;
|
||||||
mRotationLockController = Dependency.get(RotationLockController.class);
|
mIconCcwStart90ResId = iconCcwStart90ResId;
|
||||||
mAccessibilityManagerWrapper = Dependency.get(AccessibilityManagerWrapper.class);
|
mIconCwStart0ResId = iconCwStart0ResId;
|
||||||
|
mIconCwStart90ResId = iconCwStart90ResId;
|
||||||
|
mIconResId = mIconCcwStart90ResId;
|
||||||
|
|
||||||
|
mAccessibilityManager = AccessibilityManager.getInstance(context);
|
||||||
mTaskStackListener = new TaskStackListenerImpl();
|
mTaskStackListener = new TaskStackListenerImpl();
|
||||||
|
mWindowRotationProvider = windowRotationProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRotationButton(RotationButton rotationButton,
|
public void setRotationButton(RotationButton rotationButton,
|
||||||
RotationButtonUpdatesCallback updatesCallback) {
|
RotationButtonUpdatesCallback updatesCallback) {
|
||||||
mRotationButton = rotationButton;
|
mRotationButton = rotationButton;
|
||||||
mRotationButton.setRotationButtonController(this);
|
mRotationButton.setRotationButtonController(this);
|
||||||
mRotationButton.setOnClickListener(this::onRotateSuggestionClick);
|
mRotationButton.setOnClickListener(this::onRotateSuggestionClick);
|
||||||
@@ -149,7 +181,24 @@ public class RotationButtonController {
|
|||||||
mRotationButton.setUpdatesCallback(updatesCallback);
|
mRotationButton.setUpdatesCallback(updatesCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerListeners() {
|
public Context getContext() {
|
||||||
|
return mContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
registerListeners();
|
||||||
|
if (mContext.getDisplay().getDisplayId() != DEFAULT_DISPLAY) {
|
||||||
|
// Currently there is no accelerometer sensor on non-default display, disable fixed
|
||||||
|
// rotation for non-default display
|
||||||
|
onDisable2FlagChanged(StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDestroy() {
|
||||||
|
unregisterListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerListeners() {
|
||||||
if (mListenersRegistered) {
|
if (mListenersRegistered) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -157,18 +206,19 @@ public class RotationButtonController {
|
|||||||
mListenersRegistered = true;
|
mListenersRegistered = true;
|
||||||
try {
|
try {
|
||||||
WindowManagerGlobal.getWindowManagerService()
|
WindowManagerGlobal.getWindowManagerService()
|
||||||
.watchRotation(mRotationWatcher, mContext.getDisplay().getDisplayId());
|
.watchRotation(mRotationWatcher, DEFAULT_DISPLAY);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
mListenersRegistered = false;
|
mListenersRegistered = false;
|
||||||
Log.w(TAG, "RegisterListeners for the display failed");
|
Log.w(TAG, "RegisterListeners for the display failed");
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
Log.e(TAG, "RegisterListeners caught a RemoteException", e);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
|
TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unregisterListeners() {
|
public void unregisterListeners() {
|
||||||
if (!mListenersRegistered) {
|
if (!mListenersRegistered) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -177,34 +227,31 @@ public class RotationButtonController {
|
|||||||
try {
|
try {
|
||||||
WindowManagerGlobal.getWindowManagerService().removeRotationWatcher(mRotationWatcher);
|
WindowManagerGlobal.getWindowManagerService().removeRotationWatcher(mRotationWatcher);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw e.rethrowFromSystemServer();
|
Log.e(TAG, "UnregisterListeners caught a RemoteException", e);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
|
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRotationCallback(Consumer<Integer> watcher) {
|
public void setRotationCallback(Consumer<Integer> watcher) {
|
||||||
mRotWatcherListener = watcher;
|
mRotWatcherListener = watcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRotationLockedAtAngle(int rotationSuggestion) {
|
public void setRotationLockedAtAngle(int rotationSuggestion) {
|
||||||
mRotationLockController.setRotationLockedAtAngle(true /* locked */, rotationSuggestion);
|
RotationPolicy.setRotationLockAtAngle(mContext, true, rotationSuggestion);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRotationLocked() {
|
public boolean isRotationLocked() {
|
||||||
return mRotationLockController.isRotationLocked();
|
return RotationPolicy.isRotationLocked(mContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRotateSuggestionButtonState(boolean visible) {
|
public void setRotateSuggestionButtonState(boolean visible) {
|
||||||
setRotateSuggestionButtonState(visible, false /* hideImmediately */);
|
setRotateSuggestionButtonState(visible, false /* force */);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void setRotateSuggestionButtonState(final boolean visible, final boolean force) {
|
||||||
* Change the visibility of rotate suggestion button. If {@code hideImmediately} is true,
|
// At any point the button can become invisible because an a11y service became active.
|
||||||
* it doesn't wait until the completion of the running animation.
|
|
||||||
*/
|
|
||||||
void setRotateSuggestionButtonState(final boolean visible, final boolean hideImmediately) {
|
|
||||||
// At any point the the button can become invisible because an a11y service became active.
|
|
||||||
// Similarly, a call to make the button visible may be rejected because an a11y service is
|
// Similarly, a call to make the button visible may be rejected because an a11y service is
|
||||||
// active. Must account for this.
|
// active. Must account for this.
|
||||||
// Rerun a show animation to indicate change but don't rerun a hide animation
|
// Rerun a show animation to indicate change but don't rerun a hide animation
|
||||||
@@ -213,7 +260,7 @@ public class RotationButtonController {
|
|||||||
final View view = mRotationButton.getCurrentView();
|
final View view = mRotationButton.getCurrentView();
|
||||||
if (view == null) return;
|
if (view == null) return;
|
||||||
|
|
||||||
final KeyButtonDrawable currentDrawable = mRotationButton.getImageDrawable();
|
final Drawable currentDrawable = mRotationButton.getImageDrawable();
|
||||||
if (currentDrawable == null) return;
|
if (currentDrawable == null) return;
|
||||||
|
|
||||||
// Clear any pending suggestion flag as it has either been nullified or is being shown
|
// Clear any pending suggestion flag as it has either been nullified or is being shown
|
||||||
@@ -232,11 +279,13 @@ public class RotationButtonController {
|
|||||||
view.setAlpha(1f);
|
view.setAlpha(1f);
|
||||||
|
|
||||||
// Run the rotate icon's animation if it has one
|
// Run the rotate icon's animation if it has one
|
||||||
if (currentDrawable.canAnimate()) {
|
if (currentDrawable instanceof AnimatedVectorDrawable) {
|
||||||
currentDrawable.resetAnimation();
|
((AnimatedVectorDrawable) currentDrawable).reset();
|
||||||
currentDrawable.startAnimation();
|
((AnimatedVectorDrawable) currentDrawable).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(b/187754252): No idea why this doesn't work. If we remove the "false"
|
||||||
|
// we see the animation show the pressed state... but it only shows the first time.
|
||||||
if (!isRotateSuggestionIntroduced()) mViewRippler.start(view);
|
if (!isRotateSuggestionIntroduced()) mViewRippler.start(view);
|
||||||
|
|
||||||
// Set visibility unless a11y service is active.
|
// Set visibility unless a11y service is active.
|
||||||
@@ -244,7 +293,7 @@ public class RotationButtonController {
|
|||||||
} else { // Hide
|
} else { // Hide
|
||||||
mViewRippler.stop(); // Prevent any pending ripples, force hide or not
|
mViewRippler.stop(); // Prevent any pending ripples, force hide or not
|
||||||
|
|
||||||
if (hideImmediately) {
|
if (force) {
|
||||||
// If a hide animator is running stop it and make invisible
|
// If a hide animator is running stop it and make invisible
|
||||||
if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) {
|
if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) {
|
||||||
mRotateHideAnimator.pause();
|
mRotateHideAnimator.pause();
|
||||||
@@ -258,7 +307,7 @@ public class RotationButtonController {
|
|||||||
|
|
||||||
ObjectAnimator fadeOut = ObjectAnimator.ofFloat(view, "alpha", 0f);
|
ObjectAnimator fadeOut = ObjectAnimator.ofFloat(view, "alpha", 0f);
|
||||||
fadeOut.setDuration(BUTTON_FADE_IN_OUT_DURATION_MS);
|
fadeOut.setDuration(BUTTON_FADE_IN_OUT_DURATION_MS);
|
||||||
fadeOut.setInterpolator(Interpolators.LINEAR);
|
fadeOut.setInterpolator(LINEAR_INTERPOLATOR);
|
||||||
fadeOut.addListener(new AnimatorListenerAdapter() {
|
fadeOut.addListener(new AnimatorListenerAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationEnd(Animator animation) {
|
public void onAnimationEnd(Animator animation) {
|
||||||
@@ -271,29 +320,34 @@ public class RotationButtonController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRecentsAnimationRunning(boolean running) {
|
public void setDarkIntensity(float darkIntensity) {
|
||||||
|
mRotationButton.setDarkIntensity(darkIntensity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRecentsAnimationRunning(boolean running) {
|
||||||
mIsRecentsAnimationRunning = running;
|
mIsRecentsAnimationRunning = running;
|
||||||
updateRotationButtonStateInOverview();
|
updateRotationButtonStateInOverview();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setHomeRotationEnabled(boolean enabled) {
|
public void setHomeRotationEnabled(boolean enabled) {
|
||||||
mHomeRotationEnabled = enabled;
|
mHomeRotationEnabled = enabled;
|
||||||
updateRotationButtonStateInOverview();
|
updateRotationButtonStateInOverview();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateRotationButtonStateInOverview() {
|
private void updateRotationButtonStateInOverview() {
|
||||||
if (mIsRecentsAnimationRunning && !mHomeRotationEnabled) {
|
if (mIsRecentsAnimationRunning && !mHomeRotationEnabled) {
|
||||||
setRotateSuggestionButtonState(false, true /* hideImmediately */ );
|
setRotateSuggestionButtonState(false, true /* hideImmediately */);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDarkIntensity(float darkIntensity) {
|
public void onRotationProposal(int rotation, boolean isValid) {
|
||||||
mRotationButton.setDarkIntensity(darkIntensity);
|
int windowRotation = mWindowRotationProvider.get();
|
||||||
}
|
|
||||||
|
|
||||||
void onRotationProposal(int rotation, int windowRotation, boolean isValid) {
|
if (!mRotationButton.acceptRotationProposal()) {
|
||||||
if (!mRotationButton.acceptRotationProposal() || (!mHomeRotationEnabled
|
return;
|
||||||
&& mIsRecentsAnimationRunning)) {
|
}
|
||||||
|
|
||||||
|
if (!mHomeRotationEnabled && mIsRecentsAnimationRunning) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,13 +370,9 @@ public class RotationButtonController {
|
|||||||
mLastRotationSuggestion = rotation; // Remember rotation for click
|
mLastRotationSuggestion = rotation; // Remember rotation for click
|
||||||
final boolean rotationCCW = Utilities.isRotationAnimationCCW(windowRotation, rotation);
|
final boolean rotationCCW = Utilities.isRotationAnimationCCW(windowRotation, rotation);
|
||||||
if (windowRotation == Surface.ROTATION_0 || windowRotation == Surface.ROTATION_180) {
|
if (windowRotation == Surface.ROTATION_0 || windowRotation == Surface.ROTATION_180) {
|
||||||
mIconResId = rotationCCW
|
mIconResId = rotationCCW ? mIconCcwStart0ResId : mIconCwStart0ResId;
|
||||||
? R.drawable.ic_sysbar_rotate_button_ccw_start_90
|
|
||||||
: R.drawable.ic_sysbar_rotate_button_cw_start_90;
|
|
||||||
} else { // 90 or 270
|
} else { // 90 or 270
|
||||||
mIconResId = rotationCCW
|
mIconResId = rotationCCW ? mIconCcwStart90ResId : mIconCwStart90ResId;
|
||||||
? R.drawable.ic_sysbar_rotate_button_ccw_start_0
|
|
||||||
: R.drawable.ic_sysbar_rotate_button_ccw_start_0;
|
|
||||||
}
|
}
|
||||||
mRotationButton.updateIcon(mLightIconColor, mDarkIconColor);
|
mRotationButton.updateIcon(mLightIconColor, mDarkIconColor);
|
||||||
|
|
||||||
@@ -339,23 +389,31 @@ public class RotationButtonController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onDisable2FlagChanged(int state2) {
|
public void onDisable2FlagChanged(int state2) {
|
||||||
final boolean rotateSuggestionsDisabled = hasDisable2RotateSuggestionFlag(state2);
|
final boolean rotateSuggestionsDisabled = hasDisable2RotateSuggestionFlag(state2);
|
||||||
if (rotateSuggestionsDisabled) onRotationSuggestionsDisabled();
|
if (rotateSuggestionsDisabled) onRotationSuggestionsDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onNavigationBarWindowVisibilityChange(boolean showing) {
|
public void onBehaviorChanged(int displayId, @WindowInsetsController.Behavior int behavior) {
|
||||||
|
if (DEFAULT_DISPLAY != displayId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mBehavior != behavior) {
|
||||||
|
mBehavior = behavior;
|
||||||
|
showPendingRotationButtonIfNeeded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onNavigationBarWindowVisibilityChange(boolean showing) {
|
||||||
if (mIsNavigationBarShowing != showing) {
|
if (mIsNavigationBarShowing != showing) {
|
||||||
mIsNavigationBarShowing = showing;
|
mIsNavigationBarShowing = showing;
|
||||||
showPendingRotationButtonIfNeeded();
|
showPendingRotationButtonIfNeeded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onBehaviorChanged(@Behavior int behavior) {
|
public void onTaskbarStateChange(boolean visible, boolean stashed) {
|
||||||
if (mBehavior != behavior) {
|
getRotationButton().onTaskbarStateChanged(visible, stashed);
|
||||||
mBehavior = behavior;
|
|
||||||
showPendingRotationButtonIfNeeded();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showPendingRotationButtonIfNeeded() {
|
private void showPendingRotationButtonIfNeeded() {
|
||||||
@@ -364,31 +422,33 @@ public class RotationButtonController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return true when either the nav bar is visible or it's in visual immersive mode. */
|
/**
|
||||||
|
* Return true when either the task bar is visible or it's in visual immersive mode.
|
||||||
|
*/
|
||||||
|
@SuppressLint("InlinedApi")
|
||||||
private boolean canShowRotationButton() {
|
private boolean canShowRotationButton() {
|
||||||
return mIsNavigationBarShowing || mBehavior == WindowInsetsController.BEHAVIOR_DEFAULT;
|
return mIsNavigationBarShowing || mBehavior == WindowInsetsController.BEHAVIOR_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Context getContext() {
|
@DrawableRes
|
||||||
return mContext;
|
public int getIconResId() {
|
||||||
}
|
|
||||||
|
|
||||||
RotationButton getRotationButton() {
|
|
||||||
return mRotationButton;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @DrawableRes int getIconResId() {
|
|
||||||
return mIconResId;
|
return mIconResId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @ColorInt int getLightIconColor() {
|
@ColorInt
|
||||||
|
public int getLightIconColor() {
|
||||||
return mLightIconColor;
|
return mLightIconColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @ColorInt int getDarkIconColor() {
|
@ColorInt
|
||||||
|
public int getDarkIconColor() {
|
||||||
return mDarkIconColor;
|
return mDarkIconColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RotationButton getRotationButton() {
|
||||||
|
return mRotationButton;
|
||||||
|
}
|
||||||
|
|
||||||
private void onRotateSuggestionClick(View v) {
|
private void onRotateSuggestionClick(View v) {
|
||||||
mUiEventLogger.log(RotationButtonEvent.ROTATION_SUGGESTION_ACCEPTED);
|
mUiEventLogger.log(RotationButtonEvent.ROTATION_SUGGESTION_ACCEPTED);
|
||||||
incrementNumAcceptedRotationSuggestionsIfNeeded();
|
incrementNumAcceptedRotationSuggestionsIfNeeded();
|
||||||
@@ -420,7 +480,7 @@ public class RotationButtonController {
|
|||||||
* avoid losing original user rotation when display rotation is changed by entering the fixed
|
* avoid losing original user rotation when display rotation is changed by entering the fixed
|
||||||
* orientation overview.
|
* orientation overview.
|
||||||
*/
|
*/
|
||||||
void setSkipOverrideUserLockPrefsOnce() {
|
public void setSkipOverrideUserLockPrefsOnce() {
|
||||||
mSkipOverrideUserLockPrefsOnce = true;
|
mSkipOverrideUserLockPrefsOnce = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,7 +511,7 @@ public class RotationButtonController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int computeRotationProposalTimeout() {
|
private int computeRotationProposalTimeout() {
|
||||||
return mAccessibilityManagerWrapper.getRecommendedTimeoutMillis(
|
return mAccessibilityManager.getRecommendedTimeoutMillis(
|
||||||
mHoveringRotationSuggestion ? 16000 : 5000,
|
mHoveringRotationSuggestion ? 16000 : 5000,
|
||||||
AccessibilityManager.FLAG_CONTENT_CONTROLS);
|
AccessibilityManager.FLAG_CONTENT_CONTROLS);
|
||||||
}
|
}
|
||||||
@@ -513,11 +573,15 @@ public class RotationButtonController {
|
|||||||
ROTATION_SUGGESTION_ACCEPTED(207);
|
ROTATION_SUGGESTION_ACCEPTED(207);
|
||||||
|
|
||||||
private final int mId;
|
private final int mId;
|
||||||
|
|
||||||
RotationButtonEvent(int id) {
|
RotationButtonEvent(int id) {
|
||||||
mId = id;
|
mId = id;
|
||||||
}
|
}
|
||||||
@Override public int getId() {
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
return mId;
|
return mId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,6 +131,8 @@ import com.android.systemui.navigationbar.gestural.QuickswitchOrientedNavHandle;
|
|||||||
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||||
import com.android.systemui.recents.OverviewProxyService;
|
import com.android.systemui.recents.OverviewProxyService;
|
||||||
import com.android.systemui.recents.Recents;
|
import com.android.systemui.recents.Recents;
|
||||||
|
import com.android.systemui.shared.rotation.RotationButton;
|
||||||
|
import com.android.systemui.shared.rotation.RotationButtonController;
|
||||||
import com.android.systemui.settings.UserTracker;
|
import com.android.systemui.settings.UserTracker;
|
||||||
import com.android.systemui.shared.recents.utilities.Utilities;
|
import com.android.systemui.shared.recents.utilities.Utilities;
|
||||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||||
@@ -944,7 +946,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
|
|||||||
// not valid. Just ignore the rotation in this case.
|
// not valid. Just ignore the rotation in this case.
|
||||||
if (!mNavigationBarView.isAttachedToWindow()) return;
|
if (!mNavigationBarView.isAttachedToWindow()) return;
|
||||||
|
|
||||||
final int winRotation = mNavigationBarView.getDisplay().getRotation();
|
|
||||||
final boolean rotateSuggestionsDisabled = RotationButtonController
|
final boolean rotateSuggestionsDisabled = RotationButtonController
|
||||||
.hasDisable2RotateSuggestionFlag(mDisabledFlags2);
|
.hasDisable2RotateSuggestionFlag(mDisabledFlags2);
|
||||||
final RotationButtonController rotationButtonController =
|
final RotationButtonController rotationButtonController =
|
||||||
@@ -953,7 +954,6 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
|
|||||||
|
|
||||||
if (RotationContextButton.DEBUG_ROTATION) {
|
if (RotationContextButton.DEBUG_ROTATION) {
|
||||||
Log.v(TAG, "onRotationProposal proposedRotation=" + Surface.rotationToString(rotation)
|
Log.v(TAG, "onRotationProposal proposedRotation=" + Surface.rotationToString(rotation)
|
||||||
+ ", winRotation=" + Surface.rotationToString(winRotation)
|
|
||||||
+ ", isValid=" + isValid + ", mNavBarWindowState="
|
+ ", isValid=" + isValid + ", mNavBarWindowState="
|
||||||
+ StatusBarManager.windowStateToString(mNavigationBarWindowState)
|
+ StatusBarManager.windowStateToString(mNavigationBarWindowState)
|
||||||
+ ", rotateSuggestionsDisabled=" + rotateSuggestionsDisabled
|
+ ", rotateSuggestionsDisabled=" + rotateSuggestionsDisabled
|
||||||
@@ -963,7 +963,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener,
|
|||||||
// Respect the disabled flag, no need for action as flag change callback will handle hiding
|
// Respect the disabled flag, no need for action as flag change callback will handle hiding
|
||||||
if (rotateSuggestionsDisabled) return;
|
if (rotateSuggestionsDisabled) return;
|
||||||
|
|
||||||
rotationButtonController.onRotationProposal(rotation, winRotation, isValid);
|
rotationButtonController.onRotationProposal(rotation, isValid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ import com.android.systemui.Dependency;
|
|||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.animation.Interpolators;
|
import com.android.systemui.animation.Interpolators;
|
||||||
import com.android.systemui.model.SysUiState;
|
import com.android.systemui.model.SysUiState;
|
||||||
import com.android.systemui.navigationbar.RotationButton.RotationButtonUpdatesCallback;
|
|
||||||
import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
|
import com.android.systemui.navigationbar.buttons.ButtonDispatcher;
|
||||||
import com.android.systemui.navigationbar.buttons.ContextualButton;
|
import com.android.systemui.navigationbar.buttons.ContextualButton;
|
||||||
import com.android.systemui.navigationbar.buttons.ContextualButtonGroup;
|
import com.android.systemui.navigationbar.buttons.ContextualButtonGroup;
|
||||||
@@ -76,9 +75,11 @@ import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
|
|||||||
import com.android.systemui.navigationbar.buttons.NearestTouchFrame;
|
import com.android.systemui.navigationbar.buttons.NearestTouchFrame;
|
||||||
import com.android.systemui.navigationbar.buttons.RotationContextButton;
|
import com.android.systemui.navigationbar.buttons.RotationContextButton;
|
||||||
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
|
import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
|
||||||
import com.android.systemui.navigationbar.gestural.FloatingRotationButton;
|
import com.android.systemui.shared.rotation.FloatingRotationButton;
|
||||||
import com.android.systemui.recents.OverviewProxyService;
|
import com.android.systemui.recents.OverviewProxyService;
|
||||||
import com.android.systemui.recents.Recents;
|
import com.android.systemui.recents.Recents;
|
||||||
|
import com.android.systemui.shared.rotation.RotationButton.RotationButtonUpdatesCallback;
|
||||||
|
import com.android.systemui.shared.rotation.RotationButtonController;
|
||||||
import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
|
import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
|
||||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||||
import com.android.systemui.shared.system.QuickStepContract;
|
import com.android.systemui.shared.system.QuickStepContract;
|
||||||
@@ -322,9 +323,15 @@ public class NavigationBarView extends FrameLayout implements
|
|||||||
mContextualButtonGroup.addButton(accessibilityButton);
|
mContextualButtonGroup.addButton(accessibilityButton);
|
||||||
mRotationContextButton = new RotationContextButton(R.id.rotate_suggestion,
|
mRotationContextButton = new RotationContextButton(R.id.rotate_suggestion,
|
||||||
mLightContext, R.drawable.ic_sysbar_rotate_button_ccw_start_0);
|
mLightContext, R.drawable.ic_sysbar_rotate_button_ccw_start_0);
|
||||||
mFloatingRotationButton = new FloatingRotationButton(context);
|
mFloatingRotationButton = new FloatingRotationButton(context,
|
||||||
mRotationButtonController = new RotationButtonController(mLightContext,
|
R.string.accessibility_rotate_button);
|
||||||
mLightIconColor, mDarkIconColor);
|
mRotationButtonController = new RotationButtonController(mLightContext, mLightIconColor,
|
||||||
|
mDarkIconColor, R.drawable.ic_sysbar_rotate_button_ccw_start_0,
|
||||||
|
R.drawable.ic_sysbar_rotate_button_ccw_start_90,
|
||||||
|
R.drawable.ic_sysbar_rotate_button_cw_start_0,
|
||||||
|
R.drawable.ic_sysbar_rotate_button_cw_start_90,
|
||||||
|
() -> getDisplay().getRotation());
|
||||||
|
|
||||||
updateRotationButton();
|
updateRotationButton();
|
||||||
|
|
||||||
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
|
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
|
||||||
@@ -661,7 +668,7 @@ public class NavigationBarView extends FrameLayout implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setBehavior(@Behavior int behavior) {
|
public void setBehavior(@Behavior int behavior) {
|
||||||
mRotationButtonController.onBehaviorChanged(behavior);
|
mRotationButtonController.onBehaviorChanged(Display.DEFAULT_DISPLAY, behavior);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1277,6 +1284,7 @@ public class NavigationBarView extends FrameLayout implements
|
|||||||
mButtonDispatchers.valueAt(i).onDestroy();
|
mButtonDispatchers.valueAt(i).onDestroy();
|
||||||
}
|
}
|
||||||
if (mRotationButtonController != null) {
|
if (mRotationButtonController != null) {
|
||||||
|
mFloatingRotationButton.hide();
|
||||||
mRotationButtonController.unregisterListeners();
|
mRotationButtonController.unregisterListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,48 +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.systemui.navigationbar;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import com.android.systemui.navigationbar.buttons.KeyButtonDrawable;
|
|
||||||
|
|
||||||
/** Interface of a rotation button that interacts {@link RotationButtonController}. */
|
|
||||||
public interface RotationButton {
|
|
||||||
void setRotationButtonController(RotationButtonController rotationButtonController);
|
|
||||||
void setUpdatesCallback(RotationButtonUpdatesCallback updatesCallback);
|
|
||||||
View getCurrentView();
|
|
||||||
boolean show();
|
|
||||||
boolean hide();
|
|
||||||
boolean isVisible();
|
|
||||||
void updateIcon(int lightIconColor, int darkIconColor);
|
|
||||||
void setOnClickListener(View.OnClickListener onClickListener);
|
|
||||||
void setOnHoverListener(View.OnHoverListener onHoverListener);
|
|
||||||
KeyButtonDrawable getImageDrawable();
|
|
||||||
void setDarkIntensity(float darkIntensity);
|
|
||||||
default void setCanShowRotationButton(boolean canShow) {}
|
|
||||||
default boolean acceptRotationProposal() {
|
|
||||||
return getCurrentView() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback for updates provided by a rotation button
|
|
||||||
*/
|
|
||||||
interface RotationButtonUpdatesCallback {
|
|
||||||
void onVisibilityChanged(boolean isVisible);
|
|
||||||
void onPositionChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,8 +21,8 @@ import android.annotation.IdRes;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.android.systemui.navigationbar.RotationButton;
|
import com.android.systemui.shared.rotation.RotationButton;
|
||||||
import com.android.systemui.navigationbar.RotationButtonController;
|
import com.android.systemui.shared.rotation.RotationButtonController;
|
||||||
|
|
||||||
/** Containing logic for the rotation button in nav bar. */
|
/** Containing logic for the rotation button in nav bar. */
|
||||||
public class RotationContextButton extends ContextualButton implements RotationButton {
|
public class RotationContextButton extends ContextualButton implements RotationButton {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import static org.mockito.Mockito.spy;
|
|||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
import android.view.Display;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowInsetsController;
|
import android.view.WindowInsetsController;
|
||||||
|
|
||||||
@@ -31,6 +32,8 @@ import androidx.test.runner.AndroidJUnit4;
|
|||||||
|
|
||||||
import com.android.systemui.SysuiTestCase;
|
import com.android.systemui.SysuiTestCase;
|
||||||
import com.android.systemui.SysuiTestableContext;
|
import com.android.systemui.SysuiTestableContext;
|
||||||
|
import com.android.systemui.shared.rotation.RotationButton;
|
||||||
|
import com.android.systemui.shared.rotation.RotationButtonController;
|
||||||
import com.android.systemui.statusbar.policy.RotationLockController;
|
import com.android.systemui.statusbar.policy.RotationLockController;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -39,6 +42,8 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/** atest NavigationBarRotationContextTest */
|
/** atest NavigationBarRotationContextTest */
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@@ -50,6 +55,8 @@ public class NavigationBarRotationContextTest extends SysuiTestCase {
|
|||||||
InstrumentationRegistry.getContext(), getLeakCheck());
|
InstrumentationRegistry.getContext(), getLeakCheck());
|
||||||
private RotationButtonController mRotationButtonController;
|
private RotationButtonController mRotationButtonController;
|
||||||
private RotationButton mRotationButton;
|
private RotationButton mRotationButton;
|
||||||
|
private int mWindowRotation = DEFAULT_ROTATE;
|
||||||
|
private Supplier<Integer> mWindowRotationSupplier = () -> mWindowRotation;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup() {
|
public void setup() {
|
||||||
@@ -58,7 +65,15 @@ public class NavigationBarRotationContextTest extends SysuiTestCase {
|
|||||||
|
|
||||||
final View view = new View(mContext);
|
final View view = new View(mContext);
|
||||||
mRotationButton = mock(RotationButton.class);
|
mRotationButton = mock(RotationButton.class);
|
||||||
mRotationButtonController = new RotationButtonController(mContext, 0, 0);
|
mRotationButtonController = new RotationButtonController(mContext,
|
||||||
|
/* lightIconColor */ 0,
|
||||||
|
/* darkIconColor */ 0,
|
||||||
|
/* iconCcwStart0 */ 0,
|
||||||
|
/* iconCcwStart90 */ 0,
|
||||||
|
/* iconCwStart0 */ 0,
|
||||||
|
/* iconCwStart90 */ 0,
|
||||||
|
mWindowRotationSupplier
|
||||||
|
);
|
||||||
mRotationButtonController.setRotationButton(mRotationButton,
|
mRotationButtonController.setRotationButton(mRotationButton,
|
||||||
new RotationButton.RotationButtonUpdatesCallback() {
|
new RotationButton.RotationButtonUpdatesCallback() {
|
||||||
@Override
|
@Override
|
||||||
@@ -77,16 +92,16 @@ public class NavigationBarRotationContextTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOnInvalidRotationProposal() {
|
public void testOnInvalidRotationProposal() {
|
||||||
mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, DEFAULT_ROTATE + 1,
|
mWindowRotation = DEFAULT_ROTATE + 1;
|
||||||
false /* isValid */);
|
mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, false /* isValid */);
|
||||||
verify(mRotationButtonController, times(1)).setRotateSuggestionButtonState(
|
verify(mRotationButtonController, times(1)).setRotateSuggestionButtonState(
|
||||||
false /* visible */);
|
false /* visible */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOnSameRotationProposal() {
|
public void testOnSameRotationProposal() {
|
||||||
mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, DEFAULT_ROTATE,
|
mWindowRotation = DEFAULT_ROTATE;
|
||||||
true /* isValid */);
|
mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, true /* isValid */);
|
||||||
verify(mRotationButtonController, times(1)).setRotateSuggestionButtonState(
|
verify(mRotationButtonController, times(1)).setRotateSuggestionButtonState(
|
||||||
false /* visible */);
|
false /* visible */);
|
||||||
}
|
}
|
||||||
@@ -94,17 +109,17 @@ public class NavigationBarRotationContextTest extends SysuiTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testOnRotationProposalShowButtonShowNav() {
|
public void testOnRotationProposalShowButtonShowNav() {
|
||||||
// No navigation bar should not call to set visibility state
|
// No navigation bar should not call to set visibility state
|
||||||
mRotationButtonController.onBehaviorChanged(
|
mRotationButtonController.onBehaviorChanged(Display.DEFAULT_DISPLAY,
|
||||||
WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
|
WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
|
||||||
mRotationButtonController.onNavigationBarWindowVisibilityChange(false /* showing */);
|
mRotationButtonController.onNavigationBarWindowVisibilityChange(false /* showing */);
|
||||||
verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
|
verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
|
||||||
false /* visible */);
|
false /* visible */);
|
||||||
verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
|
verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
|
||||||
true /* visible */);
|
true /* visible */);
|
||||||
|
mWindowRotation = DEFAULT_ROTATE + 1;
|
||||||
|
|
||||||
// No navigation bar with rotation change should not call to set visibility state
|
// No navigation bar with rotation change should not call to set visibility state
|
||||||
mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, DEFAULT_ROTATE + 1,
|
mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, true /* isValid */);
|
||||||
true /* isValid */);
|
|
||||||
verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
|
verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
|
||||||
false /* visible */);
|
false /* visible */);
|
||||||
verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
|
verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
|
||||||
@@ -124,10 +139,10 @@ public class NavigationBarRotationContextTest extends SysuiTestCase {
|
|||||||
false /* visible */);
|
false /* visible */);
|
||||||
verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
|
verify(mRotationButtonController, times(0)).setRotateSuggestionButtonState(
|
||||||
true /* visible */);
|
true /* visible */);
|
||||||
|
mWindowRotation = DEFAULT_ROTATE + 1;
|
||||||
|
|
||||||
// Navigation bar is visible and rotation requested
|
// Navigation bar is visible and rotation requested
|
||||||
mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, DEFAULT_ROTATE + 1,
|
mRotationButtonController.onRotationProposal(DEFAULT_ROTATE, true /* isValid */);
|
||||||
true /* isValid */);
|
|
||||||
verify(mRotationButtonController, times(1)).setRotateSuggestionButtonState(
|
verify(mRotationButtonController, times(1)).setRotateSuggestionButtonState(
|
||||||
true /* visible */);
|
true /* visible */);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import android.view.Gravity
|
|||||||
import android.view.Surface
|
import android.view.Surface
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.navigationbar.gestural.FloatingRotationButtonPositionCalculator.Position
|
import com.android.systemui.shared.rotation.FloatingRotationButtonPositionCalculator
|
||||||
|
import com.android.systemui.shared.rotation.FloatingRotationButtonPositionCalculator.Position
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|||||||
Reference in New Issue
Block a user