diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml index 8e1baba956..7c0a5aece0 100644 --- a/quickstep/AndroidManifest.xml +++ b/quickstep/AndroidManifest.xml @@ -104,7 +104,8 @@ android:autoRemoveFromRecents="true" android:excludeFromRecents="true" android:theme="@style/GestureTutorialActivity" - android:exported="true"> + android:exported="true" + android:configChanges="orientation"> diff --git a/quickstep/res/drawable/rotate_prompt_bg.xml b/quickstep/res/drawable/rotate_prompt_bg.xml new file mode 100644 index 0000000000..528a2bc90d --- /dev/null +++ b/quickstep/res/drawable/rotate_prompt_bg.xml @@ -0,0 +1,21 @@ + + + + + \ No newline at end of file diff --git a/quickstep/res/drawable/rotate_tutorial_warning.xml b/quickstep/res/drawable/rotate_tutorial_warning.xml new file mode 100644 index 0000000000..d1117a4321 --- /dev/null +++ b/quickstep/res/drawable/rotate_tutorial_warning.xml @@ -0,0 +1,26 @@ + + + + diff --git a/quickstep/res/layout/gesture_tutorial_activity.xml b/quickstep/res/layout/gesture_tutorial_activity.xml index 4dc8913ef5..0e763ec734 100644 --- a/quickstep/res/layout/gesture_tutorial_activity.xml +++ b/quickstep/res/layout/gesture_tutorial_activity.xml @@ -13,7 +13,80 @@ See the License for the specific language governing permissions and limitations under the License. --> - \ No newline at end of file + android:layout_height="match_parent"> + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml index bd69f9f4ec..3b8278451d 100644 --- a/quickstep/res/values/strings.xml +++ b/quickstep/res/values/strings.xml @@ -94,6 +94,10 @@ Predicted app: %1$s + + Rotate your device + + Please rotate your device to complete the gesture navigation tutorial Make sure you swipe from the far-right or far-left edge. diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml index 612682a86b..21b7fd5139 100644 --- a/quickstep/res/values/styles.xml +++ b/quickstep/res/values/styles.xml @@ -290,4 +290,12 @@ @android:color/system_accent2_300 ?androidprv:attr/materialColorOnSecondaryFixedVariant + + + + diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java index 54c441b59e..9083d514d3 100644 --- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java @@ -147,7 +147,7 @@ final class BackGestureTutorialController extends TutorialController { @Override public void onBackGestureAttempted(BackGestureResult result) { - if (isGestureCompleted()) { + if (skipGestureAttempt()) { return; } switch (mTutorialType) { @@ -165,7 +165,7 @@ final class BackGestureTutorialController extends TutorialController { @Override public void onBackGestureProgress(float diffx, float diffy, boolean isLeftGesture) { - if (isGestureCompleted()) { + if (skipGestureAttempt()) { return; } @@ -234,7 +234,7 @@ final class BackGestureTutorialController extends TutorialController { @Override public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) { - if (isGestureCompleted()) { + if (skipGestureAttempt()) { return; } if (mTutorialType == BACK_NAVIGATION_COMPLETE) { diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java index aeac760025..62726a01d2 100644 --- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java +++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java @@ -16,6 +16,8 @@ package com.android.quickstep.interaction; import android.content.SharedPreferences; +import android.content.pm.ActivityInfo; +import android.content.res.Configuration; import android.graphics.Color; import android.graphics.Rect; import android.os.Bundle; @@ -29,6 +31,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.FragmentActivity; +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherPrefs; import com.android.launcher3.R; import com.android.launcher3.config.FeatureFlags; @@ -53,10 +57,12 @@ public class GestureSandboxActivity extends FragmentActivity { private int mCurrentStep; private int mNumSteps; + private boolean mShowRotationPrompt; private SharedPreferences mSharedPrefs; private StatsLogManager mStatsLogManager; + private View mRotationPrompt; private TISBindHelper mTISBindHelper; private TISBinder mBinder; @@ -94,9 +100,49 @@ public class GestureSandboxActivity extends FragmentActivity { .add(R.id.gesture_tutorial_fragment_container, mFragment) .commit(); + mRotationPrompt = findViewById(R.id.rotation_prompt); + if (FeatureFlags.ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) { + correctUserOrientation(); + } mTISBindHelper = new TISBindHelper(this, this::onTISConnected); } + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + // Ensure the prompt to rotate the screen is updated + if (FeatureFlags.ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) { + correctUserOrientation(); + } + } + + /** + * Gesture animations are only in landscape for large screens and portrait for mobile. This + * method enforces the following flows: + * 1) phone / two-panel closed -> lock to portrait + * 2) two-panel open / tablet + portrait -> prompt the user to rotate the screen + * 3) two-panel open / tablet + landscape -> hide potential rotating prompt + */ + private void correctUserOrientation() { + DeviceProfile deviceProfile = InvariantDeviceProfile.INSTANCE.get( + getApplicationContext()).getDeviceProfile(this); + if (deviceProfile.isTablet) { + mShowRotationPrompt = getResources().getConfiguration().orientation + == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; + updateVisibility(mRotationPrompt, mShowRotationPrompt ? View.VISIBLE : View.GONE); + } else { + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + } + } + + void updateVisibility(View view, int visibility) { + if (view == null || view.getVisibility() == visibility) { + return; + } + view.setVisibility(visibility); + } + @Override public void onAttachedToWindow() { super.onAttachedToWindow(); @@ -128,6 +174,10 @@ public class GestureSandboxActivity extends FragmentActivity { super.onSaveInstanceState(savedInstanceState); } + protected boolean isRotationPromptShowing() { + return mShowRotationPrompt; + } + protected SharedPreferences getSharedPrefs() { return mSharedPrefs; } diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java index 891f20e560..333ecbbb2c 100644 --- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java @@ -140,7 +140,7 @@ final class HomeGestureTutorialController extends SwipeUpGestureTutorialControll @Override public void onBackGestureAttempted(BackGestureResult result) { - if (isGestureCompleted()) { + if (skipGestureAttempt()) { return; } switch (mTutorialType) { @@ -167,7 +167,7 @@ final class HomeGestureTutorialController extends SwipeUpGestureTutorialControll @Override public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) { - if (isGestureCompleted()) { + if (skipGestureAttempt()) { return; } switch (mTutorialType) { diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java index 667fe4dfad..09a6bbe6b2 100644 --- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java @@ -170,7 +170,7 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont @Override public void onBackGestureAttempted(BackGestureResult result) { - if (isGestureCompleted()) { + if (skipGestureAttempt()) { return; } switch (mTutorialType) { @@ -197,7 +197,7 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont @Override public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) { - if (isGestureCompleted()) { + if (skipGestureAttempt()) { return; } switch (mTutorialType) { diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java index 0bbf373023..f1cbfcc613 100644 --- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java @@ -260,7 +260,7 @@ abstract class SwipeUpGestureTutorialController extends TutorialController { @Override public void setNavBarGestureProgress(@Nullable Float displacement) { - if (isGestureCompleted()) { + if (skipGestureAttempt()) { return; } if (mTutorialType == HOME_NAVIGATION_COMPLETE @@ -281,7 +281,7 @@ abstract class SwipeUpGestureTutorialController extends TutorialController { @Override public void onMotionPaused(boolean unused) { - if (isGestureCompleted()) { + if (skipGestureAttempt()) { return; } if (mShowTasks) { diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java index 5ec92a6542..a58f4538c8 100644 --- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java @@ -462,6 +462,10 @@ abstract class TutorialController implements BackGestureAttemptCallback, return mGestureCompleted; } + public boolean skipGestureAttempt() { + return isGestureCompleted() || mTutorialFragment.isRotationPromptShowing(); + } + void hideFeedback() { if (mFeedbackView.getVisibility() != View.VISIBLE) { return; diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java index bfad64308c..84326f5a27 100644 --- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java +++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java @@ -498,6 +498,11 @@ abstract class TutorialFragment extends GestureSandboxFragment implements OnTouc return activity != null ? activity.getStatsLogManager() : null; } + protected boolean isRotationPromptShowing() { + GestureSandboxActivity activity = getGestureSandboxActivity(); + return activity != null && activity.isRotationPromptShowing(); + } + @Nullable private SharedPreferences getSharedPreferences() { GestureSandboxActivity activity = getGestureSandboxActivity();