From ac5fa1bb605161d65756226fe6535bd822c97435 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Wed, 14 Dec 2016 11:02:39 -0800 Subject: [PATCH] Change screen pinning back to old gesture This makes the code a bit more complicated, but allows apps to receive long-press back again and also makes the mode harder to exit for toddlers. Test: Without TalkBack enabled, make sure the following works: - Enter multi-window mode with long pressing recents - Long press back gets sent to the app. - Enter screen pinning, make sure you can exit with gesture Test: With TalkBack enabled, make sure the following works: - Enter multi-window mode with long pressing recents - Long press back gets sent to the app. - Enter screen pinning, make sure you can exit with gesture Fixes: 324407 Change-Id: Icd7347aa9c60af00fdb0b3991baabb730552d097 --- .../layout/screen_pinning_request_buttons.xml | 20 +++- .../screen_pinning_request_buttons_land.xml | 20 +++- packages/SystemUI/res/values/strings.xml | 4 +- .../recents/ScreenPinningRequest.java | 8 +- .../statusbar/phone/PhoneStatusBar.java | 107 ++++++++++++------ 5 files changed, 116 insertions(+), 43 deletions(-) diff --git a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml index e3662f17b336d..c2b1009c31370 100644 --- a/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml +++ b/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml @@ -108,7 +108,25 @@ android:layout_height="@dimen/screen_pinning_request_button_height" android:layout_weight="0" android:paddingStart="@dimen/screen_pinning_request_frame_padding" - android:paddingEnd="@dimen/screen_pinning_request_frame_padding" > + android:paddingEnd="@dimen/screen_pinning_request_frame_padding" + android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent"> + + + + + android:layout_weight="0" + android:theme="@*android:style/ThemeOverlay.DeviceDefault.Accent"> + + + + Screen is pinned - This keeps it in view until you unpin. Touch & hold Back to unpin. + This keeps it in view until you unpin. Touch & hold Back and Overview to unpin. + + This keeps it in view until you unpin. Touch & hold Overview to unpin. Got it diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java index 002515d10a012..0336905cd8553 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java +++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java @@ -231,10 +231,12 @@ public class ScreenPinningRequest implements View.OnClickListener { .setVisibility(View.INVISIBLE); } + boolean touchExplorationEnabled = mAccessibilityService.isTouchExplorationEnabled(); ((TextView) mLayout.findViewById(R.id.screen_pinning_description)) - .setText(R.string.screen_pinning_description); - final int backBgVisibility = - mAccessibilityService.isEnabled() ? View.INVISIBLE : View.VISIBLE; + .setText(touchExplorationEnabled + ? R.string.screen_pinning_description_accessible + : R.string.screen_pinning_description); + final int backBgVisibility = touchExplorationEnabled ? View.INVISIBLE : View.VISIBLE; mLayout.findViewById(R.id.screen_pinning_back_bg).setVisibility(backBgVisibility); mLayout.findViewById(R.id.screen_pinning_back_bg_light).setVisibility(backBgVisibility); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index fa7a237b8a542..ea4e10297eda6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -22,7 +22,6 @@ import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN; import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN; import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; import static android.app.StatusBarManager.windowStateToString; - import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE; @@ -35,13 +34,14 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.annotation.NonNull; import android.app.ActivityManager; +import android.app.ActivityManagerNative; import android.app.ActivityOptions; -import android.app.admin.DevicePolicyManager; import android.app.IActivityManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.StatusBarManager; +import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; import android.content.ComponentCallbacks2; import android.content.ComponentName; @@ -113,6 +113,7 @@ import android.view.ViewStub; import android.view.ViewTreeObserver; import android.view.WindowManager; import android.view.WindowManagerGlobal; +import android.view.accessibility.AccessibilityEvent; import android.view.animation.AccelerateInterpolator; import android.view.animation.Interpolator; import android.widget.ImageView; @@ -148,7 +149,6 @@ import com.android.systemui.plugins.qs.QS.ActivityStarter; import com.android.systemui.plugins.qs.QS.BaseStatusBarHeader; import com.android.systemui.qs.QSFragment; import com.android.systemui.qs.QSPanel; -import com.android.systemui.recents.Recents; import com.android.systemui.recents.ScreenPinningRequest; import com.android.systemui.recents.events.EventBus; import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent; @@ -186,6 +186,7 @@ import com.android.systemui.statusbar.policy.EncryptionHelper; import com.android.systemui.statusbar.policy.FlashlightControllerImpl; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.HotspotControllerImpl; +import com.android.systemui.statusbar.policy.KeyButtonView; import com.android.systemui.statusbar.policy.KeyguardMonitorImpl; import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; import com.android.systemui.statusbar.policy.LocationControllerImpl; @@ -200,8 +201,7 @@ import com.android.systemui.statusbar.policy.UserInfoControllerImpl; import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.stack.NotificationStackScrollLayout; -import com.android.systemui.statusbar.stack.NotificationStackScrollLayout - .OnChildLocationsChangedListener; +import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener; import com.android.systemui.statusbar.stack.StackStateAnimator; import com.android.systemui.volume.VolumeComponent; @@ -670,6 +670,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private RankingMap mLatestRankingMap; private boolean mNoAnimationOnNextBarModeChange; private FalsingManager mFalsingManager; + private long mLastLockToAppLongPress; private KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() { @Override @@ -1347,28 +1348,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } }; - private View.OnLongClickListener mLongPressBackListener = new View.OnLongClickListener() { - @Override - public boolean onLongClick(View v) { - return handleLongPressBack(); - } - }; - - private View.OnLongClickListener mRecentsLongClickListener = new View.OnLongClickListener() { - - @Override - public boolean onLongClick(View v) { - if (mRecents == null || !ActivityManager.supportsMultiWindow() - || !getComponent(Divider.class).getView().getSnapAlgorithm() - .isSplitScreenFeasible()) { - return false; - } - - return toggleSplitScreenMode(MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS, - MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS); - } - }; - @Override protected boolean toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) { if (mRecents == null) { @@ -1460,11 +1439,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, recentsButton.setOnClickListener(mRecentsClickListener); recentsButton.setOnTouchListener(mRecentsPreloadOnTouchListener); recentsButton.setLongClickable(true); - recentsButton.setOnLongClickListener(mRecentsLongClickListener); + recentsButton.setOnLongClickListener(this::handleLongPressBackRecents); ButtonDispatcher backButton = mNavigationBarView.getBackButton(); backButton.setLongClickable(true); - backButton.setOnLongClickListener(mLongPressBackListener); + backButton.setOnLongClickListener(this::handleLongPressBackRecents); ButtonDispatcher homeButton = mNavigationBarView.getHomeButton(); homeButton.setOnTouchListener(mHomeActionListener); @@ -4992,16 +4971,59 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } /** - * Handles long press for back button. This exits screen pinning. + * This handles long-press of both back and recents. They are + * handled together to capture them both being long-pressed + * at the same time to exit screen pinning (lock task). + * + * When accessibility mode is on, only a long-press from recents + * is required to exit. + * + * In all other circumstances we try to pass through long-press events + * for Back, so that apps can still use it. Which can be from two things. + * 1) Not currently in screen pinning (lock task). + * 2) Back is long-pressed without recents. */ - private boolean handleLongPressBack() { + private boolean handleLongPressBackRecents(View v) { try { - IActivityManager activityManager = ActivityManager.getService(); - if (activityManager.isInLockTaskMode()) { - activityManager.stopSystemLockTaskMode(); - - // When exiting refresh disabled flags. - mNavigationBarView.setDisabledFlags(mDisabled1, true); + boolean sendBackLongPress = false; + IActivityManager activityManager = ActivityManagerNative.getDefault(); + boolean touchExplorationEnabled = mAccessibilityManager.isTouchExplorationEnabled(); + boolean inLockTaskMode = activityManager.isInLockTaskMode(); + if (inLockTaskMode && !touchExplorationEnabled) { + long time = System.currentTimeMillis(); + // If we recently long-pressed the other button then they were + // long-pressed 'together' + if ((time - mLastLockToAppLongPress) < LOCK_TO_APP_GESTURE_TOLERENCE) { + activityManager.stopLockTaskMode(); + // When exiting refresh disabled flags. + mNavigationBarView.setDisabledFlags(mDisabled1, true); + return true; + } else if ((v.getId() == R.id.back) + && !mNavigationBarView.getRecentsButton().getCurrentView().isPressed()) { + // If we aren't pressing recents right now then they presses + // won't be together, so send the standard long-press action. + sendBackLongPress = true; + } + mLastLockToAppLongPress = time; + } else { + // If this is back still need to handle sending the long-press event. + if (v.getId() == R.id.back) { + sendBackLongPress = true; + } else if (touchExplorationEnabled && inLockTaskMode) { + // When in accessibility mode a long press that is recents (not back) + // should stop lock task. + activityManager.stopLockTaskMode(); + // When exiting refresh disabled flags. + mNavigationBarView.setDisabledFlags(mDisabled1, true); + return true; + } else if (v.getId() == R.id.recent_apps) { + return handleLongPressRecents(); + } + } + if (sendBackLongPress) { + KeyButtonView keyButtonView = (KeyButtonView) v; + keyButtonView.sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS); + keyButtonView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); return true; } } catch (RemoteException e) { @@ -5010,6 +5032,17 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, return false; } + private boolean handleLongPressRecents() { + if (mRecents == null || !ActivityManager.supportsMultiWindow() + || !getComponent(Divider.class).getView().getSnapAlgorithm() + .isSplitScreenFeasible()) { + return false; + } + + return toggleSplitScreenMode(MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS, + MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS); + } + @Override public void showScreenPinningRequest(int taskId) { if (mKeyguardMonitor.isShowing()) {