diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml index f80deeba45..81b0dd297c 100644 --- a/quickstep/res/values/strings.xml +++ b/quickstep/res/values/strings.xml @@ -109,6 +109,8 @@ Swipe to go back To go back to the last screen, swipe from the left or right edge to the middle of the screen. + + To go back to the last screen, swipe with 2 fingers from the left or right edge to the middle of the screen. Make sure you swipe up from the bottom edge of the screen. @@ -123,6 +125,8 @@ Swipe to go home Swipe up from the bottom of your screen. This gesture always takes you to the Home screen. + + Swipe up with 2 fingers from the bottom of the screen. This gesture always takes you to the Home screen. Make sure you swipe up from the bottom edge of the screen. @@ -138,6 +142,8 @@ Swipe to switch apps To switch between apps, swipe up from the bottom of your screen, hold, then release. + + To switch between apps, swipe up with 2 fingers from the bottom of your screen, hold, then release. Tutorial: Assistant diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java index 9ba55778d1..35d9f22d3a 100644 --- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java @@ -33,17 +33,22 @@ final class BackGestureTutorialController extends TutorialController { } @Override - public Integer getIntroductionTitle() { + public int getIntroductionTitle() { return R.string.back_gesture_intro_title; } @Override - public Integer getIntroductionSubtitle() { + public int getIntroductionSubtitle() { return R.string.back_gesture_intro_subtitle; } @Override - public Integer getSuccessFeedbackSubtitle() { + public int getSpokenIntroductionSubtitle() { + return R.string.back_gesture_spoken_intro_subtitle; + } + + @Override + public int getSuccessFeedbackSubtitle() { return mTutorialFragment.isAtFinalStep() ? R.string.back_gesture_feedback_complete_without_follow_up : R.string.back_gesture_feedback_complete_with_overview_follow_up; diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java index 6254313f74..f519d50613 100644 --- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java @@ -32,17 +32,22 @@ final class HomeGestureTutorialController extends SwipeUpGestureTutorialControll } @Override - public Integer getIntroductionTitle() { + public int getIntroductionTitle() { return R.string.home_gesture_intro_title; } @Override - public Integer getIntroductionSubtitle() { + public int getIntroductionSubtitle() { return R.string.home_gesture_intro_subtitle; } @Override - public Integer getSuccessFeedbackSubtitle() { + public int getSpokenIntroductionSubtitle() { + return R.string.home_gesture_spoken_intro_subtitle; + } + + @Override + public int getSuccessFeedbackSubtitle() { return mTutorialFragment.isAtFinalStep() ? R.string.home_gesture_feedback_complete_without_follow_up : R.string.home_gesture_feedback_complete_with_follow_up; diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java index 09640c675b..6b016cee13 100644 --- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java @@ -42,17 +42,22 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont } @Override - public Integer getIntroductionTitle() { + public int getIntroductionTitle() { return R.string.overview_gesture_intro_title; } @Override - public Integer getIntroductionSubtitle() { + public int getIntroductionSubtitle() { return R.string.overview_gesture_intro_subtitle; } @Override - public Integer getSuccessFeedbackSubtitle() { + public int getSpokenIntroductionSubtitle() { + return R.string.overview_gesture_spoken_intro_subtitle; + } + + @Override + public int getSuccessFeedbackSubtitle() { return mTutorialFragment.getNumSteps() > 1 && mTutorialFragment.isAtFinalStep() ? R.string.overview_gesture_feedback_complete_with_follow_up : R.string.overview_gesture_feedback_complete_without_follow_up; diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java index 6a8894e88f..fa7d848a7c 100644 --- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java @@ -62,7 +62,7 @@ import java.util.ArrayList; abstract class TutorialController implements BackGestureAttemptCallback, NavBarGestureAttemptCallback { - private static final String TAG = "TutorialController"; + private static final String LOG_TAG = "TutorialController"; private static final float FINGER_DOT_VISIBLE_ALPHA = 0.7f; private static final float FINGER_DOT_SMALL_SCALE = 0.7f; @@ -217,18 +217,23 @@ abstract class TutorialController implements BackGestureAttemptCallback, } @StringRes - public Integer getIntroductionTitle() { - return null; + public int getIntroductionTitle() { + return NO_ID; } @StringRes - public Integer getIntroductionSubtitle() { - return null; + public int getIntroductionSubtitle() { + return NO_ID; } @StringRes - public Integer getSuccessFeedbackSubtitle() { - return null; + public int getSpokenIntroductionSubtitle() { + return NO_ID; + } + + @StringRes + public int getSuccessFeedbackSubtitle() { + return NO_ID; } void showFeedback() { @@ -247,7 +252,16 @@ abstract class TutorialController implements BackGestureAttemptCallback, * Show feedback reflecting a successful gesture attempt. **/ void showSuccessFeedback() { - showFeedback(getSuccessFeedbackSubtitle(), true); + int successSubtitleResId = getSuccessFeedbackSubtitle(); + if (successSubtitleResId == NO_ID) { + // Allow crash since this should never be reached with a tutorial controller used in + // production. + Log.e(LOG_TAG, + "Cannot show success feedback for tutorial step: " + mTutorialType + + ", no success feedback subtitle", + new IllegalStateException()); + } + showFeedback(successSubtitleResId, true); } /** @@ -269,6 +283,7 @@ abstract class TutorialController implements BackGestureAttemptCallback, isGestureSuccessful ? R.string.gesture_tutorial_nice : R.string.gesture_tutorial_try_again, subtitleResId, + NO_ID, isGestureSuccessful, false); } @@ -276,6 +291,7 @@ abstract class TutorialController implements BackGestureAttemptCallback, void showFeedback( int titleResId, int subtitleResId, + int spokenSubtitleResId, boolean isGestureSuccessful, boolean useGestureAnimationDelay) { mFeedbackTitleView.removeCallbacks(mTitleViewCallback); @@ -287,7 +303,10 @@ abstract class TutorialController implements BackGestureAttemptCallback, mFeedbackTitleView.setText(titleResId); TextView subtitle = mFeedbackView.findViewById(R.id.gesture_tutorial_fragment_feedback_subtitle); - subtitle.setText(subtitleResId); + subtitle.setText(spokenSubtitleResId == NO_ID + ? mContext.getText(subtitleResId) + : Utilities.wrapForTts( + mContext.getText(subtitleResId), mContext.getString(spokenSubtitleResId))); if (isGestureSuccessful) { if (mTutorialFragment.isAtFinalStep()) { showActionButton(); @@ -580,7 +599,7 @@ abstract class TutorialController implements BackGestureAttemptCallback, packageManager.getApplicationInfo( PIXEL_TIPS_APP_PACKAGE_NAME, PackageManager.GET_META_DATA)); } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, + Log.e(LOG_TAG, "Could not find app label for package name: " + PIXEL_TIPS_APP_PACKAGE_NAME + ". Defaulting to 'Pixel Tips.'", @@ -593,7 +612,7 @@ abstract class TutorialController implements BackGestureAttemptCallback, subtitleTextView.setText( mContext.getString(R.string.skip_tutorial_dialog_subtitle, tipsAppName)); } else { - Log.w(TAG, "No subtitle view in the skip tutorial dialog to update."); + Log.w(LOG_TAG, "No subtitle view in the skip tutorial dialog to update."); } Button cancelButton = (Button) contentView.findViewById( @@ -602,7 +621,7 @@ abstract class TutorialController implements BackGestureAttemptCallback, cancelButton.setOnClickListener( v -> tutorialDialog.dismiss()); } else { - Log.w(TAG, "No cancel button in the skip tutorial dialog to update."); + Log.w(LOG_TAG, "No cancel button in the skip tutorial dialog to update."); } Button confirmButton = contentView.findViewById( @@ -613,7 +632,7 @@ abstract class TutorialController implements BackGestureAttemptCallback, tutorialDialog.dismiss(); }); } else { - Log.w(TAG, "No confirm button in the skip tutorial dialog to update."); + Log.w(LOG_TAG, "No confirm button in the skip tutorial dialog to update."); } tutorialDialog.getWindow().setBackgroundDrawable( diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java index 33e800d1c0..1599c8c32d 100644 --- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java +++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java @@ -15,6 +15,8 @@ */ package com.android.quickstep.interaction; +import static android.view.View.NO_ID; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.app.Activity; @@ -211,13 +213,31 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener { if (isGestureComplete()) { mTutorialController.showSuccessFeedback(); } else if (!mIntroductionShown) { - Integer introTileStringResId = mTutorialController.getIntroductionTitle(); - Integer introSubtitleResId = mTutorialController.getIntroductionSubtitle(); - if (introTileStringResId != null && introSubtitleResId != null) { - mTutorialController.showFeedback( - introTileStringResId, introSubtitleResId, false, true); - mIntroductionShown = true; + int introTitleResId = mTutorialController.getIntroductionTitle(); + int introSubtitleResId = mTutorialController.getIntroductionSubtitle(); + if (introTitleResId == NO_ID) { + // Allow crash since this should never be reached with a tutorial controller used in + // production. + Log.e(LOG_TAG, + "Cannot show introduction feedback for tutorial step: " + mTutorialType + + ", no introduction feedback title", + new IllegalStateException()); } + if (introTitleResId == NO_ID) { + // Allow crash since this should never be reached with a tutorial controller used in + // production. + Log.e(LOG_TAG, + "Cannot show introduction feedback for tutorial step: " + mTutorialType + + ", no introduction feedback subtitle", + new IllegalStateException()); + } + mTutorialController.showFeedback( + introTitleResId, + introSubtitleResId, + mTutorialController.getSpokenIntroductionSubtitle(), + false, + true); + mIntroductionShown = true; } }