149fa016a98cef9940c883b3f620a0e90537a204eJason Monk/* 249fa016a98cef9940c883b3f620a0e90537a204eJason Monk * Copyright (C) 2017 The Android Open Source Project 349fa016a98cef9940c883b3f620a0e90537a204eJason Monk * 449fa016a98cef9940c883b3f620a0e90537a204eJason Monk * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 549fa016a98cef9940c883b3f620a0e90537a204eJason Monk * except in compliance with the License. You may obtain a copy of the License at 649fa016a98cef9940c883b3f620a0e90537a204eJason Monk * 749fa016a98cef9940c883b3f620a0e90537a204eJason Monk * http://www.apache.org/licenses/LICENSE-2.0 849fa016a98cef9940c883b3f620a0e90537a204eJason Monk * 949fa016a98cef9940c883b3f620a0e90537a204eJason Monk * Unless required by applicable law or agreed to in writing, software distributed under the 1049fa016a98cef9940c883b3f620a0e90537a204eJason Monk * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1149fa016a98cef9940c883b3f620a0e90537a204eJason Monk * KIND, either express or implied. See the License for the specific language governing 1249fa016a98cef9940c883b3f620a0e90537a204eJason Monk * permissions and limitations under the License. 1349fa016a98cef9940c883b3f620a0e90537a204eJason Monk */ 1449fa016a98cef9940c883b3f620a0e90537a204eJason Monk 1549fa016a98cef9940c883b3f620a0e90537a204eJason Monkpackage com.android.systemui.statusbar.phone; 1649fa016a98cef9940c883b3f620a0e90537a204eJason Monk 1749fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT; 1849fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN; 1949fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport static android.app.StatusBarManager.WINDOW_STATE_SHOWING; 2049fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport static android.app.StatusBarManager.windowStateToString; 2149fa016a98cef9940c883b3f620a0e90537a204eJason Monk 22ab65025833344b3b55bd146a86d48cabe254a89dMike Digmanimport static com.android.internal.view.RotationPolicy.NATURAL_ROTATION; 23ab65025833344b3b55bd146a86d48cabe254a89dMike Digman 248f25fb96e2e3c064869dad00e7234013ac22c5d7Matthew Ngimport static com.android.systemui.shared.system.NavigationBarCompat.InteractionType; 2549fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT; 262a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monkimport static com.android.systemui.statusbar.phone.StatusBar.DEBUG_WINDOW_STATE; 272a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monkimport static com.android.systemui.statusbar.phone.StatusBar.dumpBarTransitions; 289c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ngimport static com.android.systemui.OverviewProxyService.OverviewProxyListener; 2949fa016a98cef9940c883b3f620a0e90537a204eJason Monk 30048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardtimport android.accessibilityservice.AccessibilityServiceInfo; 317d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digmanimport android.animation.Animator; 327d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digmanimport android.animation.AnimatorListenerAdapter; 337d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digmanimport android.animation.ObjectAnimator; 349c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ngimport android.annotation.IdRes; 3549fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.annotation.Nullable; 3649fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.app.ActivityManager; 3749fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.app.ActivityManagerNative; 3849fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.app.Fragment; 3949fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.app.IActivityManager; 4049fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.app.StatusBarManager; 4149fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.content.BroadcastReceiver; 42b9dcd66aaeb57e8427eedb52a3d9149f395bb228Casey Burkhardtimport android.content.ContentResolver; 4349fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.content.Context; 4449fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.content.Intent; 4549fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.content.IntentFilter; 4649fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.content.res.Configuration; 4774922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardtimport android.database.ContentObserver; 4849fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.graphics.PixelFormat; 4949fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.graphics.Rect; 507d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digmanimport android.graphics.drawable.AnimatedVectorDrawable; 5149fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.inputmethodservice.InputMethodService; 5249fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.os.Binder; 5349fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.os.Bundle; 5449fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.os.Handler; 5549fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.os.IBinder; 5649fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.os.Message; 5749fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.os.RemoteException; 5849fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.os.UserHandle; 5974922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardtimport android.provider.Settings; 60865246dc9ac488a440f8ca13973dbd8c60fede1eJason Monkimport android.support.annotation.VisibleForTesting; 6149fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.telecom.TelecomManager; 6249fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.text.TextUtils; 6349fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.util.Log; 6449fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.view.IRotationWatcher.Stub; 6549fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.view.KeyEvent; 6649fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.view.LayoutInflater; 6749fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.view.MotionEvent; 6885ff7fa1687658d37c8701f45a534cb5866df077Mike Digmanimport android.view.Surface; 6949fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.view.View; 7049fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.view.ViewGroup; 7149fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.view.WindowManager; 7249fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.view.WindowManager.LayoutParams; 7349fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.view.WindowManagerGlobal; 7449fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.view.accessibility.AccessibilityEvent; 7549fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport android.view.accessibility.AccessibilityManager; 7691e587ebbc5b208f152c8a882f9e137f2525410eJason Monkimport android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener; 7749fa016a98cef9940c883b3f620a0e90537a204eJason Monk 7849fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport com.android.internal.logging.MetricsLogger; 7949fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport com.android.internal.logging.nano.MetricsProto.MetricsEvent; 80ea03be1056d44328b96559702791bdac2a466002Jason Monkimport com.android.internal.util.LatencyTracker; 819c7844cb91b43929d0a86b1c90aa1efb37f5463aJason Monkimport com.android.systemui.Dependency; 827d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digmanimport com.android.systemui.Interpolators; 831e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digmanimport com.android.systemui.OverviewProxyService; 8449fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport com.android.systemui.R; 859c7844cb91b43929d0a86b1c90aa1efb37f5463aJason Monkimport com.android.systemui.SysUiServiceProvider; 8649fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport com.android.systemui.assist.AssistManager; 8749fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport com.android.systemui.fragments.FragmentHostManager; 8849fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport com.android.systemui.fragments.FragmentHostManager.FragmentListener; 8949fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport com.android.systemui.recents.Recents; 907d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digmanimport com.android.systemui.recents.misc.SysUiTaskStackChangeListener; 917d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digmanimport com.android.systemui.shared.system.ActivityManagerWrapper; 9249fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport com.android.systemui.stackdivider.Divider; 9349fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport com.android.systemui.statusbar.CommandQueue; 9449fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport com.android.systemui.statusbar.CommandQueue.Callbacks; 9591e587ebbc5b208f152c8a882f9e137f2525410eJason Monkimport com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; 967d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digmanimport com.android.systemui.statusbar.policy.KeyButtonDrawable; 9749fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport com.android.systemui.statusbar.policy.KeyButtonView; 987d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digmanimport com.android.systemui.statusbar.policy.RotationLockController; 9949fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport com.android.systemui.statusbar.stack.StackStateAnimator; 10049fa016a98cef9940c883b3f620a0e90537a204eJason Monk 10149fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport java.io.FileDescriptor; 10249fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport java.io.PrintWriter; 103048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardtimport java.util.List; 10449fa016a98cef9940c883b3f620a0e90537a204eJason Monkimport java.util.Locale; 105121b11ff5b80f1d9e762120f9cd87834b05a5b6aMike Digmanimport java.util.Optional; 10649fa016a98cef9940c883b3f620a0e90537a204eJason Monk 10749fa016a98cef9940c883b3f620a0e90537a204eJason Monk/** 10849fa016a98cef9940c883b3f620a0e90537a204eJason Monk * Fragment containing the NavigationBarFragment. Contains logic for what happens 10949fa016a98cef9940c883b3f620a0e90537a204eJason Monk * on clicks and view states of the nav bar. 11049fa016a98cef9940c883b3f620a0e90537a204eJason Monk */ 11149fa016a98cef9940c883b3f620a0e90537a204eJason Monkpublic class NavigationBarFragment extends Fragment implements Callbacks { 11249fa016a98cef9940c883b3f620a0e90537a204eJason Monk 113d4afe152bf5cd93e5034f5b8b43b2f0fe0269a7fJason Monk public static final String TAG = "NavigationBar"; 11449fa016a98cef9940c883b3f620a0e90537a204eJason Monk private static final boolean DEBUG = false; 1153e33da67d47fb78356cc9d3eabaad3c1198acc1fMike Digman private static final boolean DEBUG_ROTATION = true; 11649fa016a98cef9940c883b3f620a0e90537a204eJason Monk private static final String EXTRA_DISABLE_STATE = "disabled_state"; 117dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman private static final String EXTRA_DISABLE2_STATE = "disabled2_state"; 11849fa016a98cef9940c883b3f620a0e90537a204eJason Monk 1191e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman private final static int BUTTON_FADE_IN_OUT_DURATION_MS = 100; 1205aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman private final static int NAVBAR_HIDDEN_PENDING_ICON_TIMEOUT_MS = 20000; 1211e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 1225075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman private static final int NUM_ACCEPTED_ROTATION_SUGGESTIONS_FOR_INTRODUCTION = 3; 1235075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman 12449fa016a98cef9940c883b3f620a0e90537a204eJason Monk /** Allow some time inbetween the long press for back and recents. */ 12549fa016a98cef9940c883b3f620a0e90537a204eJason Monk private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200; 12649fa016a98cef9940c883b3f620a0e90537a204eJason Monk 12749fa016a98cef9940c883b3f620a0e90537a204eJason Monk protected NavigationBarView mNavigationBarView = null; 12849fa016a98cef9940c883b3f620a0e90537a204eJason Monk protected AssistManager mAssistManager; 12949fa016a98cef9940c883b3f620a0e90537a204eJason Monk 13049fa016a98cef9940c883b3f620a0e90537a204eJason Monk private int mNavigationBarWindowState = WINDOW_STATE_SHOWING; 13149fa016a98cef9940c883b3f620a0e90537a204eJason Monk 13249fa016a98cef9940c883b3f620a0e90537a204eJason Monk private int mNavigationIconHints = 0; 13349fa016a98cef9940c883b3f620a0e90537a204eJason Monk private int mNavigationBarMode; 13490402957beb698799f65aa6756633554d121bc11Mike Digman private boolean mAccessibilityFeedbackEnabled; 135048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt private AccessibilityManager mAccessibilityManager; 13674922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt private MagnificationContentObserver mMagnificationObserver; 137b9dcd66aaeb57e8427eedb52a3d9149f395bb228Casey Burkhardt private ContentResolver mContentResolver; 138c94759d89804d1e8cca8c64343b19d1ebac53b32Mike Digman private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); 13949fa016a98cef9940c883b3f620a0e90537a204eJason Monk 14049fa016a98cef9940c883b3f620a0e90537a204eJason Monk private int mDisabledFlags1; 141dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman private int mDisabledFlags2; 1422a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk private StatusBar mStatusBar; 14349fa016a98cef9940c883b3f620a0e90537a204eJason Monk private Recents mRecents; 14449fa016a98cef9940c883b3f620a0e90537a204eJason Monk private Divider mDivider; 14549fa016a98cef9940c883b3f620a0e90537a204eJason Monk private WindowManager mWindowManager; 14649fa016a98cef9940c883b3f620a0e90537a204eJason Monk private CommandQueue mCommandQueue; 14749fa016a98cef9940c883b3f620a0e90537a204eJason Monk private long mLastLockToAppLongPress; 14849fa016a98cef9940c883b3f620a0e90537a204eJason Monk 14949fa016a98cef9940c883b3f620a0e90537a204eJason Monk private Locale mLocale; 15049fa016a98cef9940c883b3f620a0e90537a204eJason Monk private int mLayoutDirection; 15149fa016a98cef9940c883b3f620a0e90537a204eJason Monk 15249fa016a98cef9940c883b3f620a0e90537a204eJason Monk private int mSystemUiVisibility; 15349fa016a98cef9940c883b3f620a0e90537a204eJason Monk private LightBarController mLightBarController; 15449fa016a98cef9940c883b3f620a0e90537a204eJason Monk 155dc79e5c5801b2b6ed6b0a41d8b02832bae33a848Matthew Ng private OverviewProxyService mOverviewProxyService; 156dc79e5c5801b2b6ed6b0a41d8b02832bae33a848Matthew Ng 15749fa016a98cef9940c883b3f620a0e90537a204eJason Monk public boolean mHomeBlockedThisTouch; 15849fa016a98cef9940c883b3f620a0e90537a204eJason Monk 1597d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman private int mLastRotationSuggestion; 1605aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman private boolean mPendingRotationSuggestion; 16190402957beb698799f65aa6756633554d121bc11Mike Digman private boolean mHoveringRotationSuggestion; 1627d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman private RotationLockController mRotationLockController; 1637d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman private TaskStackListenerImpl mTaskStackListener; 1647d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman 1651e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman private final Runnable mRemoveRotationProposal = () -> setRotateSuggestionButtonState(false); 1665aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman private final Runnable mCancelPendingRotationProposal = 1675aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman () -> mPendingRotationSuggestion = false; 1687d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman private Animator mRotateHideAnimator; 1695075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman private ViewRippler mViewRippler = new ViewRippler(); 1707d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman 1719c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() { 1729c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng @Override 1739c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng public void onConnectionChanged(boolean isConnected) { 174f9e302704a3042a4a09cab5ca9dbcb9f34c4ecaaWinson Chung mNavigationBarView.updateStates(); 1759c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng updateScreenPinningGestures(); 1769c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng } 1779c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng 1789c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng @Override 1792ea93b708dbc49235b42e76a587d5f353638040fMatthew Ng public void onQuickStepStarted() { 18085a9bea67ad7c4199a95119af690eda5f9a06ce7Mike Digman // Use navbar dragging as a signal to hide the rotate button 18185a9bea67ad7c4199a95119af690eda5f9a06ce7Mike Digman setRotateSuggestionButtonState(false); 1829c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng } 1838f25fb96e2e3c064869dad00e7234013ac22c5d7Matthew Ng 1848f25fb96e2e3c064869dad00e7234013ac22c5d7Matthew Ng @Override 1858f25fb96e2e3c064869dad00e7234013ac22c5d7Matthew Ng public void onInteractionFlagsChanged(@InteractionType int flags) { 1868f25fb96e2e3c064869dad00e7234013ac22c5d7Matthew Ng mNavigationBarView.updateStates(); 187f9e302704a3042a4a09cab5ca9dbcb9f34c4ecaaWinson Chung updateScreenPinningGestures(); 1888f25fb96e2e3c064869dad00e7234013ac22c5d7Matthew Ng } 18996985e74261a0dacec66cb127821d7f2248f8438Matthew Ng 19096985e74261a0dacec66cb127821d7f2248f8438Matthew Ng @Override 19196985e74261a0dacec66cb127821d7f2248f8438Matthew Ng public void onBackButtonAlphaChanged(float alpha, boolean animate) { 19296985e74261a0dacec66cb127821d7f2248f8438Matthew Ng final ButtonDispatcher backButton = mNavigationBarView.getBackButton(); 19396985e74261a0dacec66cb127821d7f2248f8438Matthew Ng backButton.setVisibility(alpha > 0 ? View.VISIBLE : View.INVISIBLE); 19496985e74261a0dacec66cb127821d7f2248f8438Matthew Ng backButton.setAlpha(alpha, animate); 19596985e74261a0dacec66cb127821d7f2248f8438Matthew Ng } 1969c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng }; 1977d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman 19849fa016a98cef9940c883b3f620a0e90537a204eJason Monk // ----- Fragment Lifecycle Callbacks ----- 19949fa016a98cef9940c883b3f620a0e90537a204eJason Monk 20049fa016a98cef9940c883b3f620a0e90537a204eJason Monk @Override 20149fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void onCreate(@Nullable Bundle savedInstanceState) { 20249fa016a98cef9940c883b3f620a0e90537a204eJason Monk super.onCreate(savedInstanceState); 2039c7844cb91b43929d0a86b1c90aa1efb37f5463aJason Monk mCommandQueue = SysUiServiceProvider.getComponent(getContext(), CommandQueue.class); 20449fa016a98cef9940c883b3f620a0e90537a204eJason Monk mCommandQueue.addCallbacks(this); 2052a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk mStatusBar = SysUiServiceProvider.getComponent(getContext(), StatusBar.class); 2069c7844cb91b43929d0a86b1c90aa1efb37f5463aJason Monk mRecents = SysUiServiceProvider.getComponent(getContext(), Recents.class); 2079c7844cb91b43929d0a86b1c90aa1efb37f5463aJason Monk mDivider = SysUiServiceProvider.getComponent(getContext(), Divider.class); 20849fa016a98cef9940c883b3f620a0e90537a204eJason Monk mWindowManager = getContext().getSystemService(WindowManager.class); 20949fa016a98cef9940c883b3f620a0e90537a204eJason Monk mAccessibilityManager = getContext().getSystemService(AccessibilityManager.class); 21091e587ebbc5b208f152c8a882f9e137f2525410eJason Monk Dependency.get(AccessibilityManagerWrapper.class).addCallback( 21191e587ebbc5b208f152c8a882f9e137f2525410eJason Monk mAccessibilityListener); 212b9dcd66aaeb57e8427eedb52a3d9149f395bb228Casey Burkhardt mContentResolver = getContext().getContentResolver(); 21374922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt mMagnificationObserver = new MagnificationContentObserver( 21474922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt getContext().getMainThreadHandler()); 215b9dcd66aaeb57e8427eedb52a3d9149f395bb228Casey Burkhardt mContentResolver.registerContentObserver(Settings.Secure.getUriFor( 21674922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED), false, 2175d6144056493b0d657e74d13de8e751c06510357Casey Burkhardt mMagnificationObserver, UserHandle.USER_ALL); 21874922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt 21949fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (savedInstanceState != null) { 22049fa016a98cef9940c883b3f620a0e90537a204eJason Monk mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0); 221dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman mDisabledFlags2 = savedInstanceState.getInt(EXTRA_DISABLE2_STATE, 0); 22249fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 2239c7844cb91b43929d0a86b1c90aa1efb37f5463aJason Monk mAssistManager = Dependency.get(AssistManager.class); 224dc79e5c5801b2b6ed6b0a41d8b02832bae33a848Matthew Ng mOverviewProxyService = Dependency.get(OverviewProxyService.class); 22549fa016a98cef9940c883b3f620a0e90537a204eJason Monk 22649fa016a98cef9940c883b3f620a0e90537a204eJason Monk try { 22749fa016a98cef9940c883b3f620a0e90537a204eJason Monk WindowManagerGlobal.getWindowManagerService() 22835fa3c26adcb5f6577849fd0df5228b1f67cf2c6Andrii Kulian .watchRotation(mRotationWatcher, getContext().getDisplay().getDisplayId()); 22949fa016a98cef9940c883b3f620a0e90537a204eJason Monk } catch (RemoteException e) { 23049fa016a98cef9940c883b3f620a0e90537a204eJason Monk throw e.rethrowFromSystemServer(); 23149fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 2327d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman 2337d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman mRotationLockController = Dependency.get(RotationLockController.class); 2347d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman 235ab65025833344b3b55bd146a86d48cabe254a89dMike Digman // Reset user rotation pref to match that of the WindowManager if starting in locked mode 236ab65025833344b3b55bd146a86d48cabe254a89dMike Digman // This will automatically happen when switching from auto-rotate to locked mode 237ab65025833344b3b55bd146a86d48cabe254a89dMike Digman if (mRotationLockController.isRotationLocked()) { 238ab65025833344b3b55bd146a86d48cabe254a89dMike Digman final int winRotation = mWindowManager.getDefaultDisplay().getRotation(); 239ab65025833344b3b55bd146a86d48cabe254a89dMike Digman mRotationLockController.setRotationLockedAtAngle(true, winRotation); 240ab65025833344b3b55bd146a86d48cabe254a89dMike Digman } 241ab65025833344b3b55bd146a86d48cabe254a89dMike Digman 2427d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman // Register the task stack listener 2437d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman mTaskStackListener = new TaskStackListenerImpl(); 2447d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener); 24549fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 24649fa016a98cef9940c883b3f620a0e90537a204eJason Monk 24749fa016a98cef9940c883b3f620a0e90537a204eJason Monk @Override 24849fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void onDestroy() { 24949fa016a98cef9940c883b3f620a0e90537a204eJason Monk super.onDestroy(); 25049fa016a98cef9940c883b3f620a0e90537a204eJason Monk mCommandQueue.removeCallbacks(this); 25191e587ebbc5b208f152c8a882f9e137f2525410eJason Monk Dependency.get(AccessibilityManagerWrapper.class).removeCallback( 25291e587ebbc5b208f152c8a882f9e137f2525410eJason Monk mAccessibilityListener); 253b9dcd66aaeb57e8427eedb52a3d9149f395bb228Casey Burkhardt mContentResolver.unregisterContentObserver(mMagnificationObserver); 25449fa016a98cef9940c883b3f620a0e90537a204eJason Monk try { 25549fa016a98cef9940c883b3f620a0e90537a204eJason Monk WindowManagerGlobal.getWindowManagerService() 25649fa016a98cef9940c883b3f620a0e90537a204eJason Monk .removeRotationWatcher(mRotationWatcher); 25749fa016a98cef9940c883b3f620a0e90537a204eJason Monk } catch (RemoteException e) { 25849fa016a98cef9940c883b3f620a0e90537a204eJason Monk throw e.rethrowFromSystemServer(); 25949fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 2607d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman 2617d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman // Unregister the task stack listener 2627d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTaskStackListener); 26349fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 26449fa016a98cef9940c883b3f620a0e90537a204eJason Monk 26549fa016a98cef9940c883b3f620a0e90537a204eJason Monk @Override 26649fa016a98cef9940c883b3f620a0e90537a204eJason Monk public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 26749fa016a98cef9940c883b3f620a0e90537a204eJason Monk Bundle savedInstanceState) { 26849fa016a98cef9940c883b3f620a0e90537a204eJason Monk return inflater.inflate(R.layout.navigation_bar, container, false); 26949fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 27049fa016a98cef9940c883b3f620a0e90537a204eJason Monk 27149fa016a98cef9940c883b3f620a0e90537a204eJason Monk @Override 27249fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 27349fa016a98cef9940c883b3f620a0e90537a204eJason Monk super.onViewCreated(view, savedInstanceState); 27449fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarView = (NavigationBarView) view; 27549fa016a98cef9940c883b3f620a0e90537a204eJason Monk 27649fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarView.setDisabledFlags(mDisabledFlags1); 27778f88d10ba61ebe25457aaeefc88b8a2460998e4Matthew Ng mNavigationBarView.setComponents(mRecents, mDivider, mStatusBar.getPanel()); 27849fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarView.setOnVerticalChangedListener(this::onVerticalChanged); 27949fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarView.setOnTouchListener(this::onNavigationTouch); 28049fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (savedInstanceState != null) { 28149fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarView.getLightTransitionsController().restoreState(savedInstanceState); 28249fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 28349fa016a98cef9940c883b3f620a0e90537a204eJason Monk 28449fa016a98cef9940c883b3f620a0e90537a204eJason Monk prepareNavigationBarView(); 28549fa016a98cef9940c883b3f620a0e90537a204eJason Monk checkNavBarModes(); 28649fa016a98cef9940c883b3f620a0e90537a204eJason Monk 287dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman setDisabled2Flags(mDisabledFlags2); 288dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman 28949fa016a98cef9940c883b3f620a0e90537a204eJason Monk IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF); 29049fa016a98cef9940c883b3f620a0e90537a204eJason Monk filter.addAction(Intent.ACTION_SCREEN_ON); 291a858c5f60f405621ee9b333c910084ec35150ceaPhil Weaver filter.addAction(Intent.ACTION_USER_SWITCHED); 29249fa016a98cef9940c883b3f620a0e90537a204eJason Monk getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); 293d002a0a96eb857804b3aafbcd32cf66a378c5b6cSiarhei Vishniakou notifyNavigationBarScreenOn(); 2949c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng mOverviewProxyService.addCallback(mOverviewProxyListener); 29549fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 29649fa016a98cef9940c883b3f620a0e90537a204eJason Monk 29749fa016a98cef9940c883b3f620a0e90537a204eJason Monk @Override 29849fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void onDestroyView() { 29949fa016a98cef9940c883b3f620a0e90537a204eJason Monk super.onDestroyView(); 300aa573e9e8632552d1fa8bdd6b0ee408ff9a93a6bJason Monk mNavigationBarView.getLightTransitionsController().destroy(getContext()); 3019c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng mOverviewProxyService.removeCallback(mOverviewProxyListener); 30249fa016a98cef9940c883b3f620a0e90537a204eJason Monk getContext().unregisterReceiver(mBroadcastReceiver); 30349fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 30449fa016a98cef9940c883b3f620a0e90537a204eJason Monk 30549fa016a98cef9940c883b3f620a0e90537a204eJason Monk @Override 30649fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void onSaveInstanceState(Bundle outState) { 30749fa016a98cef9940c883b3f620a0e90537a204eJason Monk super.onSaveInstanceState(outState); 30849fa016a98cef9940c883b3f620a0e90537a204eJason Monk outState.putInt(EXTRA_DISABLE_STATE, mDisabledFlags1); 309dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman outState.putInt(EXTRA_DISABLE2_STATE, mDisabledFlags2); 31049fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (mNavigationBarView != null) { 31149fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarView.getLightTransitionsController().saveState(outState); 31249fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 31349fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 31449fa016a98cef9940c883b3f620a0e90537a204eJason Monk 31549fa016a98cef9940c883b3f620a0e90537a204eJason Monk @Override 31649fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void onConfigurationChanged(Configuration newConfig) { 31749fa016a98cef9940c883b3f620a0e90537a204eJason Monk super.onConfigurationChanged(newConfig); 31849fa016a98cef9940c883b3f620a0e90537a204eJason Monk final Locale locale = getContext().getResources().getConfiguration().locale; 31949fa016a98cef9940c883b3f620a0e90537a204eJason Monk final int ld = TextUtils.getLayoutDirectionFromLocale(locale); 32049fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (!locale.equals(mLocale) || ld != mLayoutDirection) { 32149fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (DEBUG) { 32249fa016a98cef9940c883b3f620a0e90537a204eJason Monk Log.v(TAG, String.format( 32349fa016a98cef9940c883b3f620a0e90537a204eJason Monk "config changed locale/LD: %s (%d) -> %s (%d)", mLocale, mLayoutDirection, 32449fa016a98cef9940c883b3f620a0e90537a204eJason Monk locale, ld)); 32549fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 32649fa016a98cef9940c883b3f620a0e90537a204eJason Monk mLocale = locale; 32749fa016a98cef9940c883b3f620a0e90537a204eJason Monk mLayoutDirection = ld; 32849fa016a98cef9940c883b3f620a0e90537a204eJason Monk refreshLayout(ld); 32949fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 33049fa016a98cef9940c883b3f620a0e90537a204eJason Monk repositionNavigationBar(); 33149fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 33249fa016a98cef9940c883b3f620a0e90537a204eJason Monk 33349fa016a98cef9940c883b3f620a0e90537a204eJason Monk @Override 33449fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) { 33549fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (mNavigationBarView != null) { 33649fa016a98cef9940c883b3f620a0e90537a204eJason Monk pw.print(" mNavigationBarWindowState="); 33749fa016a98cef9940c883b3f620a0e90537a204eJason Monk pw.println(windowStateToString(mNavigationBarWindowState)); 33849fa016a98cef9940c883b3f620a0e90537a204eJason Monk pw.print(" mNavigationBarMode="); 33949fa016a98cef9940c883b3f620a0e90537a204eJason Monk pw.println(BarTransitions.modeToString(mNavigationBarMode)); 34049fa016a98cef9940c883b3f620a0e90537a204eJason Monk dumpBarTransitions(pw, "mNavigationBarView", mNavigationBarView.getBarTransitions()); 34149fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 34249fa016a98cef9940c883b3f620a0e90537a204eJason Monk 34349fa016a98cef9940c883b3f620a0e90537a204eJason Monk pw.print(" mNavigationBarView="); 34449fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (mNavigationBarView == null) { 34549fa016a98cef9940c883b3f620a0e90537a204eJason Monk pw.println("null"); 34649fa016a98cef9940c883b3f620a0e90537a204eJason Monk } else { 34749fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarView.dump(fd, pw, args); 34849fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 34949fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 35049fa016a98cef9940c883b3f620a0e90537a204eJason Monk 35149fa016a98cef9940c883b3f620a0e90537a204eJason Monk // ----- CommandQueue Callbacks ----- 35249fa016a98cef9940c883b3f620a0e90537a204eJason Monk 35349fa016a98cef9940c883b3f620a0e90537a204eJason Monk @Override 35449fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void setImeWindowStatus(IBinder token, int vis, int backDisposition, 35549fa016a98cef9940c883b3f620a0e90537a204eJason Monk boolean showImeSwitcher) { 35649fa016a98cef9940c883b3f620a0e90537a204eJason Monk boolean imeShown = (vis & InputMethodService.IME_VISIBLE) != 0; 35749fa016a98cef9940c883b3f620a0e90537a204eJason Monk int hints = mNavigationIconHints; 358386f50e04f6e93894a38951cf9e946e9fa952af8Yohei Yukawa switch (backDisposition) { 359386f50e04f6e93894a38951cf9e946e9fa952af8Yohei Yukawa case InputMethodService.BACK_DISPOSITION_DEFAULT: 360386f50e04f6e93894a38951cf9e946e9fa952af8Yohei Yukawa case InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS: 361386f50e04f6e93894a38951cf9e946e9fa952af8Yohei Yukawa case InputMethodService.BACK_DISPOSITION_WILL_DISMISS: 362386f50e04f6e93894a38951cf9e946e9fa952af8Yohei Yukawa if (imeShown) { 363386f50e04f6e93894a38951cf9e946e9fa952af8Yohei Yukawa hints |= NAVIGATION_HINT_BACK_ALT; 364386f50e04f6e93894a38951cf9e946e9fa952af8Yohei Yukawa } else { 365386f50e04f6e93894a38951cf9e946e9fa952af8Yohei Yukawa hints &= ~NAVIGATION_HINT_BACK_ALT; 366386f50e04f6e93894a38951cf9e946e9fa952af8Yohei Yukawa } 367386f50e04f6e93894a38951cf9e946e9fa952af8Yohei Yukawa break; 368386f50e04f6e93894a38951cf9e946e9fa952af8Yohei Yukawa case InputMethodService.BACK_DISPOSITION_ADJUST_NOTHING: 369386f50e04f6e93894a38951cf9e946e9fa952af8Yohei Yukawa hints &= ~NAVIGATION_HINT_BACK_ALT; 370386f50e04f6e93894a38951cf9e946e9fa952af8Yohei Yukawa break; 37149fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 37249fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (showImeSwitcher) { 37349fa016a98cef9940c883b3f620a0e90537a204eJason Monk hints |= NAVIGATION_HINT_IME_SHOWN; 37449fa016a98cef9940c883b3f620a0e90537a204eJason Monk } else { 37549fa016a98cef9940c883b3f620a0e90537a204eJason Monk hints &= ~NAVIGATION_HINT_IME_SHOWN; 37649fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 37749fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (hints == mNavigationIconHints) return; 37849fa016a98cef9940c883b3f620a0e90537a204eJason Monk 37949fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationIconHints = hints; 38049fa016a98cef9940c883b3f620a0e90537a204eJason Monk 38149fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (mNavigationBarView != null) { 38249fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarView.setNavigationIconHints(hints); 38349fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 3842a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk mStatusBar.checkBarModes(); 38549fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 38649fa016a98cef9940c883b3f620a0e90537a204eJason Monk 38749fa016a98cef9940c883b3f620a0e90537a204eJason Monk @Override 38849fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void topAppWindowChanged(boolean showMenu) { 38949fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (mNavigationBarView != null) { 39049fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarView.setMenuVisibility(showMenu); 39149fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 39249fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 39349fa016a98cef9940c883b3f620a0e90537a204eJason Monk 39449fa016a98cef9940c883b3f620a0e90537a204eJason Monk @Override 39549fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void setWindowState(int window, int state) { 39649fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (mNavigationBarView != null 39749fa016a98cef9940c883b3f620a0e90537a204eJason Monk && window == StatusBarManager.WINDOW_NAVIGATION_BAR 39849fa016a98cef9940c883b3f620a0e90537a204eJason Monk && mNavigationBarWindowState != state) { 39949fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarWindowState = state; 40049fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (DEBUG_WINDOW_STATE) Log.d(TAG, "Navigation bar " + windowStateToString(state)); 4015aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman 4025aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman // If the navbar is visible, show the rotate button if there's a pending suggestion 4035aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman if (state == WINDOW_STATE_SHOWING && mPendingRotationSuggestion) { 4045aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman showAndLogRotationSuggestion(); 4055aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman } 40649fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 40749fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 40849fa016a98cef9940c883b3f620a0e90537a204eJason Monk 4097d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman @Override 410e07773175a55807e68aba6cd8a69b2401b748883Mike Digman public void onRotationProposal(final int rotation, boolean isValid) { 4113e33da67d47fb78356cc9d3eabaad3c1198acc1fMike Digman final int winRotation = mWindowManager.getDefaultDisplay().getRotation(); 412dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman final boolean rotateSuggestionsDisabled = hasDisable2RotateSuggestionFlag(mDisabledFlags2); 4133e33da67d47fb78356cc9d3eabaad3c1198acc1fMike Digman if (DEBUG_ROTATION) { 4143e33da67d47fb78356cc9d3eabaad3c1198acc1fMike Digman Log.v(TAG, "onRotationProposal proposedRotation=" + Surface.rotationToString(rotation) 4153e33da67d47fb78356cc9d3eabaad3c1198acc1fMike Digman + ", winRotation=" + Surface.rotationToString(winRotation) 4163e33da67d47fb78356cc9d3eabaad3c1198acc1fMike Digman + ", isValid=" + isValid + ", mNavBarWindowState=" 4173e33da67d47fb78356cc9d3eabaad3c1198acc1fMike Digman + StatusBarManager.windowStateToString(mNavigationBarWindowState) 418dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman + ", rotateSuggestionsDisabled=" + rotateSuggestionsDisabled 4193e33da67d47fb78356cc9d3eabaad3c1198acc1fMike Digman + ", isRotateButtonVisible=" + (mNavigationBarView == null ? "null" : 4203e33da67d47fb78356cc9d3eabaad3c1198acc1fMike Digman mNavigationBarView.isRotateButtonVisible())); 4213e33da67d47fb78356cc9d3eabaad3c1198acc1fMike Digman } 4223e33da67d47fb78356cc9d3eabaad3c1198acc1fMike Digman 423dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman // Respect the disabled flag, no need for action as flag change callback will handle hiding 424dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman if (rotateSuggestionsDisabled) return; 425dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman 426e07773175a55807e68aba6cd8a69b2401b748883Mike Digman // This method will be called on rotation suggestion changes even if the proposed rotation 427e07773175a55807e68aba6cd8a69b2401b748883Mike Digman // is not valid for the top app. Use invalid rotation choices as a signal to remove the 428e07773175a55807e68aba6cd8a69b2401b748883Mike Digman // rotate button if shown. 429e07773175a55807e68aba6cd8a69b2401b748883Mike Digman if (!isValid) { 4301e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman setRotateSuggestionButtonState(false); 431e07773175a55807e68aba6cd8a69b2401b748883Mike Digman return; 432e07773175a55807e68aba6cd8a69b2401b748883Mike Digman } 433e07773175a55807e68aba6cd8a69b2401b748883Mike Digman 4345aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman // If window rotation matches suggested rotation, remove any current suggestions 4351e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (rotation == winRotation) { 4365aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman getView().removeCallbacks(mRemoveRotationProposal); 4371e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman setRotateSuggestionButtonState(false); 4385aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman return; 4395aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman } 4405aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman 4415aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman // Prepare to show the navbar icon by updating the icon style to change anim params 4425aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman mLastRotationSuggestion = rotation; // Remember rotation for click 4435aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman if (mNavigationBarView != null) { 4445aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman final boolean rotationCCW = isRotationAnimationCCW(winRotation, rotation); 4455aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman int style; 4465aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman if (winRotation == Surface.ROTATION_0 || winRotation == Surface.ROTATION_180) { 4475aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman style = rotationCCW ? R.style.RotateButtonCCWStart90 : 4485aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman R.style.RotateButtonCWStart90; 4495aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman } else { // 90 or 270 4505aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman style = rotationCCW ? R.style.RotateButtonCCWStart0 : 4515aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman R.style.RotateButtonCWStart0; 4521e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman } 4535aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman mNavigationBarView.updateRotateSuggestionButtonStyle(style, true); 4545aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman } 4555aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman 4565aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman if (mNavigationBarWindowState != WINDOW_STATE_SHOWING) { 4575aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman // If the navbar isn't shown, flag the rotate icon to be shown should the navbar become 4585aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman // visible given some time limit. 4595aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman mPendingRotationSuggestion = true; 4605aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman getView().removeCallbacks(mCancelPendingRotationProposal); 4615aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman getView().postDelayed(mCancelPendingRotationProposal, 4625aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman NAVBAR_HIDDEN_PENDING_ICON_TIMEOUT_MS); 4631e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 4645aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman } else { // The navbar is visible so show the icon right away 4655aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman showAndLogRotationSuggestion(); 4667d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman } 4677d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman } 4687d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman 469dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman private void onRotationSuggestionsDisabled() { 470dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman // Immediately hide the rotate button and clear any planned removal 471dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman setRotateSuggestionButtonState(false, true); 472e14c475043ee6932f3dc1eddf449ca1c83536418Mike Digman 473e14c475043ee6932f3dc1eddf449ca1c83536418Mike Digman // This method can be called before view setup is done, ensure getView isn't null 474e14c475043ee6932f3dc1eddf449ca1c83536418Mike Digman final View v = getView(); 475e14c475043ee6932f3dc1eddf449ca1c83536418Mike Digman if (v != null) v.removeCallbacks(mRemoveRotationProposal); 476dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman } 477dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman 4785aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman private void showAndLogRotationSuggestion() { 4795aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman setRotateSuggestionButtonState(true); 4805aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman rescheduleRotationTimeout(false); 4815aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman mMetricsLogger.visible(MetricsEvent.ROTATION_SUGGESTION_SHOWN); 4825aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman } 4835aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman 4841e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman private boolean isRotationAnimationCCW(int from, int to) { 4851e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman // All 180deg WM rotation animations are CCW, match that 4861e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (from == Surface.ROTATION_0 && to == Surface.ROTATION_90) return false; 4871e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (from == Surface.ROTATION_0 && to == Surface.ROTATION_180) return true; //180d so CCW 4881e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (from == Surface.ROTATION_0 && to == Surface.ROTATION_270) return true; 4891e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (from == Surface.ROTATION_90 && to == Surface.ROTATION_0) return true; 4901e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (from == Surface.ROTATION_90 && to == Surface.ROTATION_180) return false; 4911e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (from == Surface.ROTATION_90 && to == Surface.ROTATION_270) return true; //180d so CCW 4921e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (from == Surface.ROTATION_180 && to == Surface.ROTATION_0) return true; //180d so CCW 4931e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (from == Surface.ROTATION_180 && to == Surface.ROTATION_90) return true; 4941e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (from == Surface.ROTATION_180 && to == Surface.ROTATION_270) return false; 4951e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (from == Surface.ROTATION_270 && to == Surface.ROTATION_0) return false; 4961e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (from == Surface.ROTATION_270 && to == Surface.ROTATION_90) return true; //180d so CCW 4971e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (from == Surface.ROTATION_270 && to == Surface.ROTATION_180) return true; 4981e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman return false; // Default 499a48cf192f37bc94740594a1731716403bb03ec39Mike Digman } 500a48cf192f37bc94740594a1731716403bb03ec39Mike Digman 5011e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman public void setRotateSuggestionButtonState(final boolean visible) { 5021e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman setRotateSuggestionButtonState(visible, false); 5031e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman } 5041e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5051e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman public void setRotateSuggestionButtonState(final boolean visible, final boolean force) { 5061e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (mNavigationBarView == null) return; 5071e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5081e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman // At any point the the button can become invisible because an a11y service became active. 5091e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman // Similarly, a call to make the button visible may be rejected because an a11y service is 5101e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman // active. Must account for this. 5111e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5121e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman ButtonDispatcher rotBtn = mNavigationBarView.getRotateSuggestionButton(); 5131e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman final boolean currentlyVisible = mNavigationBarView.isRotateButtonVisible(); 5141e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5151e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman // Rerun a show animation to indicate change but don't rerun a hide animation 5161e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (!visible && !currentlyVisible) return; 5171e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5181e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman View view = rotBtn.getCurrentView(); 5191e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (view == null) return; 5201e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5211e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman KeyButtonDrawable kbd = rotBtn.getImageDrawable(); 5221e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (kbd == null) return; 5231e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5241e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman // The KBD and AVD is recreated every new valid suggestion because of style changes. 5251e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman AnimatedVectorDrawable animIcon = null; 5261e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (kbd.getDrawable(0) instanceof AnimatedVectorDrawable) { 5271e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman animIcon = (AnimatedVectorDrawable) kbd.getDrawable(0); 5281e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman } 5291e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5305aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman // Clear any pending suggestion flag as it has either been nullified or is being shown 5315aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman mPendingRotationSuggestion = false; 532f4c989962cd8accf027b1f10d4cbd51249886b33Mike Digman if (getView() != null) getView().removeCallbacks(mCancelPendingRotationProposal); 5335aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman 5345aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman // Handle the visibility change and animation 5351e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (visible) { // Appear and change (cannot force) 53685a9bea67ad7c4199a95119af690eda5f9a06ce7Mike Digman // Stop and clear any currently running hide animations 5371e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) { 53885a9bea67ad7c4199a95119af690eda5f9a06ce7Mike Digman mRotateHideAnimator.cancel(); 5391e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman } 54085a9bea67ad7c4199a95119af690eda5f9a06ce7Mike Digman mRotateHideAnimator = null; 5411e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5421e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman // Reset the alpha if any has changed due to hide animation 5431e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman view.setAlpha(1f); 5441e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5451e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman // Run the rotate icon's animation if it has one 5461e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (animIcon != null) { 5471e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman animIcon.reset(); 5481e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman animIcon.start(); 5491e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman } 5501e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5515075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman if (!isRotateSuggestionIntroduced()) mViewRippler.start(view); 5525075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman 5531e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman // Set visibility, may fail if a11y service is active. 5541e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman // If invisible, call will stop animation. 5559b50b76700b2b0b0271e99bf844aa005f9192568Mike Digman int appliedVisibility = mNavigationBarView.setRotateButtonVisibility(true); 5569b50b76700b2b0b0271e99bf844aa005f9192568Mike Digman if (appliedVisibility == View.VISIBLE) { 5579b50b76700b2b0b0271e99bf844aa005f9192568Mike Digman // If the button will actually become visible and the navbar is about to hide, 5589b50b76700b2b0b0271e99bf844aa005f9192568Mike Digman // tell the statusbar to keep it around for longer 5599b50b76700b2b0b0271e99bf844aa005f9192568Mike Digman mStatusBar.touchAutoHide(); 5609b50b76700b2b0b0271e99bf844aa005f9192568Mike Digman } 5611e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5621e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman } else { // Hide 5631e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5645075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman mViewRippler.stop(); // Prevent any pending ripples, force hide or not 5655075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman 5661e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (force) { 5671e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman // If a hide animator is running stop it and make invisible 5681e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) { 5691e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman mRotateHideAnimator.pause(); 5701e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman } 5711e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman mNavigationBarView.setRotateButtonVisibility(false); 5721e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman return; 5731e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman } 5741e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5751e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman // Don't start any new hide animations if one is running 5761e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) return; 5771e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5781e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman ObjectAnimator fadeOut = ObjectAnimator.ofFloat(view, "alpha", 5791e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 0f); 5801e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman fadeOut.setDuration(BUTTON_FADE_IN_OUT_DURATION_MS); 5811e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman fadeOut.setInterpolator(Interpolators.LINEAR); 5821e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman fadeOut.addListener(new AnimatorListenerAdapter() { 5831e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman @Override 5841e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman public void onAnimationEnd(Animator animation) { 5851e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman mNavigationBarView.setRotateButtonVisibility(false); 5861e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman } 5871e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman }); 5881e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman 5891e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman mRotateHideAnimator = fadeOut; 5901e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman fadeOut.start(); 591a48cf192f37bc94740594a1731716403bb03ec39Mike Digman } 592a48cf192f37bc94740594a1731716403bb03ec39Mike Digman } 593a48cf192f37bc94740594a1731716403bb03ec39Mike Digman 59490402957beb698799f65aa6756633554d121bc11Mike Digman private void rescheduleRotationTimeout(final boolean reasonHover) { 59590402957beb698799f65aa6756633554d121bc11Mike Digman // May be called due to a new rotation proposal or a change in hover state 59690402957beb698799f65aa6756633554d121bc11Mike Digman if (reasonHover) { 59790402957beb698799f65aa6756633554d121bc11Mike Digman // Don't reschedule if a hide animator is running 5981e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) return; 59990402957beb698799f65aa6756633554d121bc11Mike Digman // Don't reschedule if not visible 6001e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman if (!mNavigationBarView.isRotateButtonVisible()) return; 60190402957beb698799f65aa6756633554d121bc11Mike Digman } 60290402957beb698799f65aa6756633554d121bc11Mike Digman 6035aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman getView().removeCallbacks(mRemoveRotationProposal); // Stop any pending removal 6045aeca79673d142f9924f71fc6055c46d837a95e7Mike Digman getView().postDelayed(mRemoveRotationProposal, 60590402957beb698799f65aa6756633554d121bc11Mike Digman computeRotationProposalTimeout()); // Schedule timeout 60690402957beb698799f65aa6756633554d121bc11Mike Digman } 60790402957beb698799f65aa6756633554d121bc11Mike Digman 60890402957beb698799f65aa6756633554d121bc11Mike Digman private int computeRotationProposalTimeout() { 60990402957beb698799f65aa6756633554d121bc11Mike Digman if (mAccessibilityFeedbackEnabled) return 20000; 61090402957beb698799f65aa6756633554d121bc11Mike Digman if (mHoveringRotationSuggestion) return 16000; 611d13e43b2bdd583215805433b1dceb7eeb6e317f9Mike Digman return 10000; 61290402957beb698799f65aa6756633554d121bc11Mike Digman } 61390402957beb698799f65aa6756633554d121bc11Mike Digman 6145075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman private boolean isRotateSuggestionIntroduced() { 6155075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman ContentResolver cr = getContext().getContentResolver(); 6165075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman return Settings.Secure.getInt(cr, Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED, 0) 6175075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman >= NUM_ACCEPTED_ROTATION_SUGGESTIONS_FOR_INTRODUCTION; 6185075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman } 6195075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman 6205075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman private void incrementNumAcceptedRotationSuggestionsIfNeeded() { 6215075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman // Get the number of accepted suggestions 6225075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman ContentResolver cr = getContext().getContentResolver(); 6235075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman final int numSuggestions = Settings.Secure.getInt(cr, 6245075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED, 0); 6255075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman 6265075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman // Increment the number of accepted suggestions only if it would change intro mode 6275075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman if (numSuggestions < NUM_ACCEPTED_ROTATION_SUGGESTIONS_FOR_INTRODUCTION) { 6285075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman Settings.Secure.putInt(cr, Settings.Secure.NUM_ROTATION_SUGGESTIONS_ACCEPTED, 6295075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman numSuggestions + 1); 6305075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman } 6315075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman } 6325075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman 6332a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk // Injected from StatusBar at creation. 63449fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void setCurrentSysuiVisibility(int systemUiVisibility) { 63549fa016a98cef9940c883b3f620a0e90537a204eJason Monk mSystemUiVisibility = systemUiVisibility; 6362a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk mNavigationBarMode = mStatusBar.computeBarMode(0, mSystemUiVisibility, 63749fa016a98cef9940c883b3f620a0e90537a204eJason Monk View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT, 63849fa016a98cef9940c883b3f620a0e90537a204eJason Monk View.NAVIGATION_BAR_TRANSPARENT); 63949fa016a98cef9940c883b3f620a0e90537a204eJason Monk checkNavBarModes(); 6402a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk mStatusBar.touchAutoHide(); 64149fa016a98cef9940c883b3f620a0e90537a204eJason Monk mLightBarController.onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */, 64249fa016a98cef9940c883b3f620a0e90537a204eJason Monk true /* nbModeChanged */, mNavigationBarMode); 64349fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 64449fa016a98cef9940c883b3f620a0e90537a204eJason Monk 64549fa016a98cef9940c883b3f620a0e90537a204eJason Monk @Override 64649fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis, 64749fa016a98cef9940c883b3f620a0e90537a204eJason Monk int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) { 64849fa016a98cef9940c883b3f620a0e90537a204eJason Monk final int oldVal = mSystemUiVisibility; 64949fa016a98cef9940c883b3f620a0e90537a204eJason Monk final int newVal = (oldVal & ~mask) | (vis & mask); 65049fa016a98cef9940c883b3f620a0e90537a204eJason Monk final int diff = newVal ^ oldVal; 65149fa016a98cef9940c883b3f620a0e90537a204eJason Monk boolean nbModeChanged = false; 65249fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (diff != 0) { 65349fa016a98cef9940c883b3f620a0e90537a204eJason Monk mSystemUiVisibility = newVal; 65449fa016a98cef9940c883b3f620a0e90537a204eJason Monk 65549fa016a98cef9940c883b3f620a0e90537a204eJason Monk // update navigation bar mode 65649fa016a98cef9940c883b3f620a0e90537a204eJason Monk final int nbMode = getView() == null 6572a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk ? -1 : mStatusBar.computeBarMode(oldVal, newVal, 65849fa016a98cef9940c883b3f620a0e90537a204eJason Monk View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT, 65949fa016a98cef9940c883b3f620a0e90537a204eJason Monk View.NAVIGATION_BAR_TRANSPARENT); 66049fa016a98cef9940c883b3f620a0e90537a204eJason Monk nbModeChanged = nbMode != -1; 66149fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (nbModeChanged) { 66249fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (mNavigationBarMode != nbMode) { 66349fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarMode = nbMode; 66449fa016a98cef9940c883b3f620a0e90537a204eJason Monk checkNavBarModes(); 66549fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 6662a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk mStatusBar.touchAutoHide(); 66749fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 66849fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 66949fa016a98cef9940c883b3f620a0e90537a204eJason Monk 67049fa016a98cef9940c883b3f620a0e90537a204eJason Monk mLightBarController.onNavigationVisibilityChanged(vis, mask, nbModeChanged, 67149fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarMode); 67249fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 67349fa016a98cef9940c883b3f620a0e90537a204eJason Monk 67449fa016a98cef9940c883b3f620a0e90537a204eJason Monk @Override 67549fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void disable(int state1, int state2, boolean animate) { 676dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman // Navigation bar flags are in both state1 and state2. 677dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman final int masked = state1 & (StatusBarManager.DISABLE_HOME 67849fa016a98cef9940c883b3f620a0e90537a204eJason Monk | StatusBarManager.DISABLE_RECENT 67949fa016a98cef9940c883b3f620a0e90537a204eJason Monk | StatusBarManager.DISABLE_BACK 68049fa016a98cef9940c883b3f620a0e90537a204eJason Monk | StatusBarManager.DISABLE_SEARCH); 68149fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (masked != mDisabledFlags1) { 68249fa016a98cef9940c883b3f620a0e90537a204eJason Monk mDisabledFlags1 = masked; 68349fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state1); 6849c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng updateScreenPinningGestures(); 68549fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 686dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman 687dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman final int masked2 = state2 & (StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS); 688dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman if (masked2 != mDisabledFlags2) { 689dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman mDisabledFlags2 = masked2; 690dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman setDisabled2Flags(masked2); 691dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman } 692dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman } 693dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman 694dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman private void setDisabled2Flags(int state2) { 695dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman // Method only called on change of disable2 flags 696dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman final boolean rotateSuggestionsDisabled = hasDisable2RotateSuggestionFlag(state2); 697dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman if (rotateSuggestionsDisabled) onRotationSuggestionsDisabled(); 698dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman } 699dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman 700dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman private boolean hasDisable2RotateSuggestionFlag(int disable2Flags) { 701dd2f49edb68996ef8d1a62e68a0493d9f98d5feaMike Digman return (disable2Flags & StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS) != 0; 70249fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 70349fa016a98cef9940c883b3f620a0e90537a204eJason Monk 70449fa016a98cef9940c883b3f620a0e90537a204eJason Monk // ----- Internal stuffz ----- 70549fa016a98cef9940c883b3f620a0e90537a204eJason Monk 70649fa016a98cef9940c883b3f620a0e90537a204eJason Monk private void refreshLayout(int layoutDirection) { 70749fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (mNavigationBarView != null) { 70849fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarView.setLayoutDirection(layoutDirection); 70949fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 71049fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 71149fa016a98cef9940c883b3f620a0e90537a204eJason Monk 71249fa016a98cef9940c883b3f620a0e90537a204eJason Monk private boolean shouldDisableNavbarGestures() { 7132a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk return !mStatusBar.isDeviceProvisioned() 714fee0b5b26a4b2ccb8aa6396ce903d0a187b26851Matthew Ng || (mDisabledFlags1 & StatusBarManager.DISABLE_SEARCH) != 0; 71549fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 71649fa016a98cef9940c883b3f620a0e90537a204eJason Monk 71749fa016a98cef9940c883b3f620a0e90537a204eJason Monk private void repositionNavigationBar() { 71849fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (mNavigationBarView == null || !mNavigationBarView.isAttachedToWindow()) return; 71949fa016a98cef9940c883b3f620a0e90537a204eJason Monk 72049fa016a98cef9940c883b3f620a0e90537a204eJason Monk prepareNavigationBarView(); 72149fa016a98cef9940c883b3f620a0e90537a204eJason Monk 72249fa016a98cef9940c883b3f620a0e90537a204eJason Monk mWindowManager.updateViewLayout((View) mNavigationBarView.getParent(), 72349fa016a98cef9940c883b3f620a0e90537a204eJason Monk ((View) mNavigationBarView.getParent()).getLayoutParams()); 72449fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 72549fa016a98cef9940c883b3f620a0e90537a204eJason Monk 7269c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng private void updateScreenPinningGestures() { 7279c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng if (mNavigationBarView == null) { 7289c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng return; 7299c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng } 7309c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng 7319c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng // Change the cancel pin gesture to home and back if recents button is invisible 7329c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng boolean recentsVisible = mNavigationBarView.isRecentsButtonVisible(); 7339c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng ButtonDispatcher backButton = mNavigationBarView.getBackButton(); 7349c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng if (recentsVisible) { 7359c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng backButton.setOnLongClickListener(this::onLongPressBackRecents); 7369c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng } else { 7379c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng backButton.setOnLongClickListener(this::onLongPressBackHome); 7389c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng } 7399c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng } 7409c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng 741d002a0a96eb857804b3aafbcd32cf66a378c5b6cSiarhei Vishniakou private void notifyNavigationBarScreenOn() { 742d0a73e7aa4f40e8cdb2f25edd9c3946beaf5c957Matthew Ng mNavigationBarView.updateNavButtonIcons(); 74349fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 74449fa016a98cef9940c883b3f620a0e90537a204eJason Monk 74549fa016a98cef9940c883b3f620a0e90537a204eJason Monk private void prepareNavigationBarView() { 74649fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarView.reorient(); 74749fa016a98cef9940c883b3f620a0e90537a204eJason Monk 74849fa016a98cef9940c883b3f620a0e90537a204eJason Monk ButtonDispatcher recentsButton = mNavigationBarView.getRecentsButton(); 74949fa016a98cef9940c883b3f620a0e90537a204eJason Monk recentsButton.setOnClickListener(this::onRecentsClick); 75049fa016a98cef9940c883b3f620a0e90537a204eJason Monk recentsButton.setOnTouchListener(this::onRecentsTouch); 75149fa016a98cef9940c883b3f620a0e90537a204eJason Monk recentsButton.setLongClickable(true); 75249fa016a98cef9940c883b3f620a0e90537a204eJason Monk recentsButton.setOnLongClickListener(this::onLongPressBackRecents); 75349fa016a98cef9940c883b3f620a0e90537a204eJason Monk 75449fa016a98cef9940c883b3f620a0e90537a204eJason Monk ButtonDispatcher backButton = mNavigationBarView.getBackButton(); 75549fa016a98cef9940c883b3f620a0e90537a204eJason Monk backButton.setLongClickable(true); 75649fa016a98cef9940c883b3f620a0e90537a204eJason Monk 75749fa016a98cef9940c883b3f620a0e90537a204eJason Monk ButtonDispatcher homeButton = mNavigationBarView.getHomeButton(); 75849fa016a98cef9940c883b3f620a0e90537a204eJason Monk homeButton.setOnTouchListener(this::onHomeTouch); 759fee0b5b26a4b2ccb8aa6396ce903d0a187b26851Matthew Ng homeButton.setOnLongClickListener(this::onHomeLongClick); 760048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt 761048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton(); 762048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt accessibilityButton.setOnClickListener(this::onAccessibilityClick); 763048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick); 764db9a77401356fac8b77fbf9f8180863ea4eeb924Phil Weaver updateAccessibilityServicesState(mAccessibilityManager); 7657d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman 7667d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman ButtonDispatcher rotateSuggestionButton = mNavigationBarView.getRotateSuggestionButton(); 7677d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman rotateSuggestionButton.setOnClickListener(this::onRotateSuggestionClick); 76890402957beb698799f65aa6756633554d121bc11Mike Digman rotateSuggestionButton.setOnHoverListener(this::onRotateSuggestionHover); 7699c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng updateScreenPinningGestures(); 77049fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 77149fa016a98cef9940c883b3f620a0e90537a204eJason Monk 77249fa016a98cef9940c883b3f620a0e90537a204eJason Monk private boolean onHomeTouch(View v, MotionEvent event) { 77349fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (mHomeBlockedThisTouch && event.getActionMasked() != MotionEvent.ACTION_DOWN) { 77449fa016a98cef9940c883b3f620a0e90537a204eJason Monk return true; 77549fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 77649fa016a98cef9940c883b3f620a0e90537a204eJason Monk // If an incoming call is ringing, HOME is totally disabled. 77749fa016a98cef9940c883b3f620a0e90537a204eJason Monk // (The user is already on the InCallUI at this point, 77849fa016a98cef9940c883b3f620a0e90537a204eJason Monk // and his ONLY options are to answer or reject the call.) 77949fa016a98cef9940c883b3f620a0e90537a204eJason Monk switch (event.getAction()) { 78049fa016a98cef9940c883b3f620a0e90537a204eJason Monk case MotionEvent.ACTION_DOWN: 78149fa016a98cef9940c883b3f620a0e90537a204eJason Monk mHomeBlockedThisTouch = false; 78249fa016a98cef9940c883b3f620a0e90537a204eJason Monk TelecomManager telecomManager = 78349fa016a98cef9940c883b3f620a0e90537a204eJason Monk getContext().getSystemService(TelecomManager.class); 78449fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (telecomManager != null && telecomManager.isRinging()) { 7852a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk if (mStatusBar.isKeyguardShowing()) { 78649fa016a98cef9940c883b3f620a0e90537a204eJason Monk Log.i(TAG, "Ignoring HOME; there's a ringing incoming call. " + 78749fa016a98cef9940c883b3f620a0e90537a204eJason Monk "No heads up"); 78849fa016a98cef9940c883b3f620a0e90537a204eJason Monk mHomeBlockedThisTouch = true; 78949fa016a98cef9940c883b3f620a0e90537a204eJason Monk return true; 79049fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 79149fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 79249fa016a98cef9940c883b3f620a0e90537a204eJason Monk break; 79349fa016a98cef9940c883b3f620a0e90537a204eJason Monk case MotionEvent.ACTION_UP: 79449fa016a98cef9940c883b3f620a0e90537a204eJason Monk case MotionEvent.ACTION_CANCEL: 7952a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk mStatusBar.awakenDreams(); 79649fa016a98cef9940c883b3f620a0e90537a204eJason Monk break; 79749fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 79849fa016a98cef9940c883b3f620a0e90537a204eJason Monk return false; 79949fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 80049fa016a98cef9940c883b3f620a0e90537a204eJason Monk 80149fa016a98cef9940c883b3f620a0e90537a204eJason Monk private void onVerticalChanged(boolean isVertical) { 8022a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk mStatusBar.setQsScrimEnabled(!isVertical); 80349fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 80449fa016a98cef9940c883b3f620a0e90537a204eJason Monk 80549fa016a98cef9940c883b3f620a0e90537a204eJason Monk private boolean onNavigationTouch(View v, MotionEvent event) { 806cb5d316646df62e9ca84cdf0b03ce7d53ae6396bEliot Courtney mStatusBar.checkUserAutohide(event); 80749fa016a98cef9940c883b3f620a0e90537a204eJason Monk return false; 80849fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 80949fa016a98cef9940c883b3f620a0e90537a204eJason Monk 810865246dc9ac488a440f8ca13973dbd8c60fede1eJason Monk @VisibleForTesting 811865246dc9ac488a440f8ca13973dbd8c60fede1eJason Monk boolean onHomeLongClick(View v) { 8126ff33b7f5364d83fc2034af03f53efdb28d36b6eMatthew Ng if (!mNavigationBarView.isRecentsButtonVisible() 8136ff33b7f5364d83fc2034af03f53efdb28d36b6eMatthew Ng && ActivityManagerWrapper.getInstance().isScreenPinningActive()) { 814fee0b5b26a4b2ccb8aa6396ce903d0a187b26851Matthew Ng return onLongPressBackHome(v); 815fee0b5b26a4b2ccb8aa6396ce903d0a187b26851Matthew Ng } 81649fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (shouldDisableNavbarGestures()) { 81749fa016a98cef9940c883b3f620a0e90537a204eJason Monk return false; 81849fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 8192ea93b708dbc49235b42e76a587d5f353638040fMatthew Ng mNavigationBarView.onNavigationButtonLongPress(v); 820c94759d89804d1e8cca8c64343b19d1ebac53b32Mike Digman mMetricsLogger.action(MetricsEvent.ACTION_ASSIST_LONG_PRESS); 82149fa016a98cef9940c883b3f620a0e90537a204eJason Monk mAssistManager.startAssist(new Bundle() /* args */); 8222a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk mStatusBar.awakenDreams(); 823dc79e5c5801b2b6ed6b0a41d8b02832bae33a848Matthew Ng 82449fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (mNavigationBarView != null) { 82549fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarView.abortCurrentGesture(); 82649fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 82749fa016a98cef9940c883b3f620a0e90537a204eJason Monk return true; 82849fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 82949fa016a98cef9940c883b3f620a0e90537a204eJason Monk 83049fa016a98cef9940c883b3f620a0e90537a204eJason Monk // additional optimization when we have software system buttons - start loading the recent 83149fa016a98cef9940c883b3f620a0e90537a204eJason Monk // tasks on touch down 83249fa016a98cef9940c883b3f620a0e90537a204eJason Monk private boolean onRecentsTouch(View v, MotionEvent event) { 83349fa016a98cef9940c883b3f620a0e90537a204eJason Monk int action = event.getAction() & MotionEvent.ACTION_MASK; 83449fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (action == MotionEvent.ACTION_DOWN) { 83549fa016a98cef9940c883b3f620a0e90537a204eJason Monk mCommandQueue.preloadRecentApps(); 83649fa016a98cef9940c883b3f620a0e90537a204eJason Monk } else if (action == MotionEvent.ACTION_CANCEL) { 83749fa016a98cef9940c883b3f620a0e90537a204eJason Monk mCommandQueue.cancelPreloadRecentApps(); 83849fa016a98cef9940c883b3f620a0e90537a204eJason Monk } else if (action == MotionEvent.ACTION_UP) { 83949fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (!v.isPressed()) { 84049fa016a98cef9940c883b3f620a0e90537a204eJason Monk mCommandQueue.cancelPreloadRecentApps(); 84149fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 84249fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 84349fa016a98cef9940c883b3f620a0e90537a204eJason Monk return false; 84449fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 84549fa016a98cef9940c883b3f620a0e90537a204eJason Monk 84649fa016a98cef9940c883b3f620a0e90537a204eJason Monk private void onRecentsClick(View v) { 84749fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (LatencyTracker.isEnabled(getContext())) { 84849fa016a98cef9940c883b3f620a0e90537a204eJason Monk LatencyTracker.getInstance(getContext()).onActionStart( 84949fa016a98cef9940c883b3f620a0e90537a204eJason Monk LatencyTracker.ACTION_TOGGLE_RECENTS); 85049fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 8512a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk mStatusBar.awakenDreams(); 85249fa016a98cef9940c883b3f620a0e90537a204eJason Monk mCommandQueue.toggleRecentApps(); 85349fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 85449fa016a98cef9940c883b3f620a0e90537a204eJason Monk 8559c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng private boolean onLongPressBackHome(View v) { 8562ea93b708dbc49235b42e76a587d5f353638040fMatthew Ng mNavigationBarView.onNavigationButtonLongPress(v); 8579c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng return onLongPressNavigationButtons(v, R.id.back, R.id.home); 8589c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng } 8599c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng 8609c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng private boolean onLongPressBackRecents(View v) { 8612ea93b708dbc49235b42e76a587d5f353638040fMatthew Ng mNavigationBarView.onNavigationButtonLongPress(v); 8629c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng return onLongPressNavigationButtons(v, R.id.back, R.id.recent_apps); 8639c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng } 8649c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng 86549fa016a98cef9940c883b3f620a0e90537a204eJason Monk /** 8669c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng * This handles long-press of both back and recents/home. Back is the common button with 8679c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng * combination of recents if it is visible or home if recents is invisible. 8689c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng * They are handled together to capture them both being long-pressed 86949fa016a98cef9940c883b3f620a0e90537a204eJason Monk * at the same time to exit screen pinning (lock task). 87049fa016a98cef9940c883b3f620a0e90537a204eJason Monk * 8719c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng * When accessibility mode is on, only a long-press from recents/home 87249fa016a98cef9940c883b3f620a0e90537a204eJason Monk * is required to exit. 87349fa016a98cef9940c883b3f620a0e90537a204eJason Monk * 87449fa016a98cef9940c883b3f620a0e90537a204eJason Monk * In all other circumstances we try to pass through long-press events 87549fa016a98cef9940c883b3f620a0e90537a204eJason Monk * for Back, so that apps can still use it. Which can be from two things. 87649fa016a98cef9940c883b3f620a0e90537a204eJason Monk * 1) Not currently in screen pinning (lock task). 8779c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng * 2) Back is long-pressed without recents/home. 87849fa016a98cef9940c883b3f620a0e90537a204eJason Monk */ 8799c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng private boolean onLongPressNavigationButtons(View v, @IdRes int btnId1, @IdRes int btnId2) { 88049fa016a98cef9940c883b3f620a0e90537a204eJason Monk try { 88149fa016a98cef9940c883b3f620a0e90537a204eJason Monk boolean sendBackLongPress = false; 88249fa016a98cef9940c883b3f620a0e90537a204eJason Monk IActivityManager activityManager = ActivityManagerNative.getDefault(); 88349fa016a98cef9940c883b3f620a0e90537a204eJason Monk boolean touchExplorationEnabled = mAccessibilityManager.isTouchExplorationEnabled(); 88449fa016a98cef9940c883b3f620a0e90537a204eJason Monk boolean inLockTaskMode = activityManager.isInLockTaskMode(); 88549fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (inLockTaskMode && !touchExplorationEnabled) { 88649fa016a98cef9940c883b3f620a0e90537a204eJason Monk long time = System.currentTimeMillis(); 8879c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng 88849fa016a98cef9940c883b3f620a0e90537a204eJason Monk // If we recently long-pressed the other button then they were 88949fa016a98cef9940c883b3f620a0e90537a204eJason Monk // long-pressed 'together' 89049fa016a98cef9940c883b3f620a0e90537a204eJason Monk if ((time - mLastLockToAppLongPress) < LOCK_TO_APP_GESTURE_TOLERENCE) { 891a83859ffaa4d339729cbc1a8c114b73c6afedb00Benjamin Franz activityManager.stopSystemLockTaskMode(); 89249fa016a98cef9940c883b3f620a0e90537a204eJason Monk // When exiting refresh disabled flags. 893d0a73e7aa4f40e8cdb2f25edd9c3946beaf5c957Matthew Ng mNavigationBarView.updateNavButtonIcons(); 89449fa016a98cef9940c883b3f620a0e90537a204eJason Monk return true; 8959c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng } else if (v.getId() == btnId1) { 8969c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng ButtonDispatcher button = btnId2 == R.id.recent_apps 8979c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng ? mNavigationBarView.getRecentsButton() 8989c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng : mNavigationBarView.getHomeButton(); 8999c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng if (!button.getCurrentView().isPressed()) { 9009c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng // If we aren't pressing recents/home right now then they presses 9019c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng // won't be together, so send the standard long-press action. 9029c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng sendBackLongPress = true; 9039c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng } 90449fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 90549fa016a98cef9940c883b3f620a0e90537a204eJason Monk mLastLockToAppLongPress = time; 90649fa016a98cef9940c883b3f620a0e90537a204eJason Monk } else { 90749fa016a98cef9940c883b3f620a0e90537a204eJason Monk // If this is back still need to handle sending the long-press event. 9089c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng if (v.getId() == btnId1) { 90949fa016a98cef9940c883b3f620a0e90537a204eJason Monk sendBackLongPress = true; 91049fa016a98cef9940c883b3f620a0e90537a204eJason Monk } else if (touchExplorationEnabled && inLockTaskMode) { 9119c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng // When in accessibility mode a long press that is recents/home (not back) 91249fa016a98cef9940c883b3f620a0e90537a204eJason Monk // should stop lock task. 913a83859ffaa4d339729cbc1a8c114b73c6afedb00Benjamin Franz activityManager.stopSystemLockTaskMode(); 91449fa016a98cef9940c883b3f620a0e90537a204eJason Monk // When exiting refresh disabled flags. 915d0a73e7aa4f40e8cdb2f25edd9c3946beaf5c957Matthew Ng mNavigationBarView.updateNavButtonIcons(); 91649fa016a98cef9940c883b3f620a0e90537a204eJason Monk return true; 9179c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng } else if (v.getId() == btnId2) { 9189c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng return btnId2 == R.id.recent_apps 9199c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng ? onLongPressRecents() 9209c3bce5c4444bcf98bc6342fa5c448345bb67a6cMatthew Ng : onHomeLongClick(mNavigationBarView.getHomeButton().getCurrentView()); 92149fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 92249fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 92349fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (sendBackLongPress) { 92449fa016a98cef9940c883b3f620a0e90537a204eJason Monk KeyButtonView keyButtonView = (KeyButtonView) v; 92549fa016a98cef9940c883b3f620a0e90537a204eJason Monk keyButtonView.sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS); 92649fa016a98cef9940c883b3f620a0e90537a204eJason Monk keyButtonView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); 92749fa016a98cef9940c883b3f620a0e90537a204eJason Monk return true; 92849fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 92949fa016a98cef9940c883b3f620a0e90537a204eJason Monk } catch (RemoteException e) { 93049fa016a98cef9940c883b3f620a0e90537a204eJason Monk Log.d(TAG, "Unable to reach activity manager", e); 93149fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 93249fa016a98cef9940c883b3f620a0e90537a204eJason Monk return false; 93349fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 93449fa016a98cef9940c883b3f620a0e90537a204eJason Monk 93549fa016a98cef9940c883b3f620a0e90537a204eJason Monk private boolean onLongPressRecents() { 9369be3a060827154617eed9132c64431af56d98eb4Erik Wolsheimer if (mRecents == null || !ActivityManager.supportsMultiWindow(getContext()) 93743db6d26d8cfc7004c0f71f7e8f8de59081f6ccdMatthew Ng || !mDivider.getView().getSnapAlgorithm().isSplitScreenFeasible() 938074c4344f5f32a6c92ec1736cf0132242da11a21Winson Chung || Recents.getConfiguration().isLowRamDevice 939074c4344f5f32a6c92ec1736cf0132242da11a21Winson Chung // If we are connected to the overview service, then disable the recents button 940074c4344f5f32a6c92ec1736cf0132242da11a21Winson Chung || mOverviewProxyService.getProxy() != null) { 94149fa016a98cef9940c883b3f620a0e90537a204eJason Monk return false; 94249fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 94349fa016a98cef9940c883b3f620a0e90537a204eJason Monk 9442a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk return mStatusBar.toggleSplitScreenMode(MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS, 94549fa016a98cef9940c883b3f620a0e90537a204eJason Monk MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS); 94649fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 94749fa016a98cef9940c883b3f620a0e90537a204eJason Monk 948048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt private void onAccessibilityClick(View v) { 949048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt mAccessibilityManager.notifyAccessibilityButtonClicked(); 950048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt } 951048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt 952048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt private boolean onAccessibilityLongClick(View v) { 9535e8b980c5d6bc282b51b3ddfc8722ff973c7e885Casey Burkhardt Intent intent = new Intent(AccessibilityManager.ACTION_CHOOSE_ACCESSIBILITY_BUTTON); 9545e8b980c5d6bc282b51b3ddfc8722ff973c7e885Casey Burkhardt intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 9555d6144056493b0d657e74d13de8e751c06510357Casey Burkhardt v.getContext().startActivityAsUser(intent, UserHandle.CURRENT); 956048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt return true; 957048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt } 958048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt 959db9a77401356fac8b77fbf9f8180863ea4eeb924Phil Weaver private void updateAccessibilityServicesState(AccessibilityManager accessibilityManager) { 96074922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt int requestingServices = 0; 96174922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt try { 9625d6144056493b0d657e74d13de8e751c06510357Casey Burkhardt if (Settings.Secure.getIntForUser(mContentResolver, 9635d6144056493b0d657e74d13de8e751c06510357Casey Burkhardt Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 9645d6144056493b0d657e74d13de8e751c06510357Casey Burkhardt UserHandle.USER_CURRENT) == 1) { 96574922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt requestingServices++; 96674922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt } 96774922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt } catch (Settings.SettingNotFoundException e) { 96874922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt } 96974922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt 97090402957beb698799f65aa6756633554d121bc11Mike Digman boolean feedbackEnabled = false; 9715d6144056493b0d657e74d13de8e751c06510357Casey Burkhardt // AccessibilityManagerService resolves services for the current user since the local 9725d6144056493b0d657e74d13de8e751c06510357Casey Burkhardt // AccessibilityManager is created from a Context with the INTERACT_ACROSS_USERS permission 973048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt final List<AccessibilityServiceInfo> services = 974db9a77401356fac8b77fbf9f8180863ea4eeb924Phil Weaver accessibilityManager.getEnabledAccessibilityServiceList( 975048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt AccessibilityServiceInfo.FEEDBACK_ALL_MASK); 976048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt for (int i = services.size() - 1; i >= 0; --i) { 977048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt AccessibilityServiceInfo info = services.get(i); 978048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt if ((info.flags & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0) { 979048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt requestingServices++; 980048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt } 98190402957beb698799f65aa6756633554d121bc11Mike Digman 98290402957beb698799f65aa6756633554d121bc11Mike Digman if (info.feedbackType != 0 && info.feedbackType != 98390402957beb698799f65aa6756633554d121bc11Mike Digman AccessibilityServiceInfo.FEEDBACK_GENERIC) { 98490402957beb698799f65aa6756633554d121bc11Mike Digman feedbackEnabled = true; 98590402957beb698799f65aa6756633554d121bc11Mike Digman } 986048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt } 987048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt 98890402957beb698799f65aa6756633554d121bc11Mike Digman mAccessibilityFeedbackEnabled = feedbackEnabled; 98990402957beb698799f65aa6756633554d121bc11Mike Digman 990048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt final boolean showAccessibilityButton = requestingServices >= 1; 991048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt final boolean targetSelection = requestingServices >= 2; 992048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt mNavigationBarView.setAccessibilityButtonState(showAccessibilityButton, targetSelection); 993048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt } 994048c2bc19af4cfcb5e959f1bc07fbfa03a72e330Casey Burkhardt 9957d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman private void onRotateSuggestionClick(View v) { 996c94759d89804d1e8cca8c64343b19d1ebac53b32Mike Digman mMetricsLogger.action(MetricsEvent.ACTION_ROTATION_SUGGESTION_ACCEPTED); 9975075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman incrementNumAcceptedRotationSuggestionsIfNeeded(); 9987d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman mRotationLockController.setRotationLockedAtAngle(true, mLastRotationSuggestion); 9997d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman } 10007d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman 100190402957beb698799f65aa6756633554d121bc11Mike Digman private boolean onRotateSuggestionHover(View v, MotionEvent event) { 100290402957beb698799f65aa6756633554d121bc11Mike Digman final int action = event.getActionMasked(); 100390402957beb698799f65aa6756633554d121bc11Mike Digman mHoveringRotationSuggestion = (action == MotionEvent.ACTION_HOVER_ENTER) 100490402957beb698799f65aa6756633554d121bc11Mike Digman || (action == MotionEvent.ACTION_HOVER_MOVE); 100590402957beb698799f65aa6756633554d121bc11Mike Digman rescheduleRotationTimeout(true); 100690402957beb698799f65aa6756633554d121bc11Mike Digman return false; // Must return false so a11y hover events are dispatched correctly. 100790402957beb698799f65aa6756633554d121bc11Mike Digman } 100890402957beb698799f65aa6756633554d121bc11Mike Digman 10092a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk // ----- Methods that StatusBar talks to (should be minimized) ----- 101049fa016a98cef9940c883b3f620a0e90537a204eJason Monk 101149fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void setLightBarController(LightBarController lightBarController) { 101249fa016a98cef9940c883b3f620a0e90537a204eJason Monk mLightBarController = lightBarController; 101349fa016a98cef9940c883b3f620a0e90537a204eJason Monk mLightBarController.setNavigationBar(mNavigationBarView.getLightTransitionsController()); 101449fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 101549fa016a98cef9940c883b3f620a0e90537a204eJason Monk 101649fa016a98cef9940c883b3f620a0e90537a204eJason Monk public boolean isSemiTransparent() { 101749fa016a98cef9940c883b3f620a0e90537a204eJason Monk return mNavigationBarMode == MODE_SEMI_TRANSPARENT; 101849fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 101949fa016a98cef9940c883b3f620a0e90537a204eJason Monk 102049fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void disableAnimationsDuringHide(long delay) { 102149fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarView.setLayoutTransitionsEnabled(false); 102249fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarView.postDelayed(() -> mNavigationBarView.setLayoutTransitionsEnabled(true), 102349fa016a98cef9940c883b3f620a0e90537a204eJason Monk delay + StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE); 102449fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 102549fa016a98cef9940c883b3f620a0e90537a204eJason Monk 102649fa016a98cef9940c883b3f620a0e90537a204eJason Monk public BarTransitions getBarTransitions() { 102749fa016a98cef9940c883b3f620a0e90537a204eJason Monk return mNavigationBarView.getBarTransitions(); 102849fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 102949fa016a98cef9940c883b3f620a0e90537a204eJason Monk 103049fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void checkNavBarModes() { 10312a6ea9c2a1b52b0386270ec73e1e6d6a9b614a34Jason Monk mStatusBar.checkBarMode(mNavigationBarMode, 103249fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarWindowState, mNavigationBarView.getBarTransitions()); 103349fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 103449fa016a98cef9940c883b3f620a0e90537a204eJason Monk 103549fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void finishBarAnimations() { 103649fa016a98cef9940c883b3f620a0e90537a204eJason Monk mNavigationBarView.getBarTransitions().finishAnimations(); 103749fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 103849fa016a98cef9940c883b3f620a0e90537a204eJason Monk 103991e587ebbc5b208f152c8a882f9e137f2525410eJason Monk private final AccessibilityServicesStateChangeListener mAccessibilityListener = 104091e587ebbc5b208f152c8a882f9e137f2525410eJason Monk this::updateAccessibilityServicesState; 104191e587ebbc5b208f152c8a882f9e137f2525410eJason Monk 104274922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt private class MagnificationContentObserver extends ContentObserver { 104374922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt 104474922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt public MagnificationContentObserver(Handler handler) { 104574922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt super(handler); 104674922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt } 104774922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt 104874922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt @Override 104974922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt public void onChange(boolean selfChange) { 1050db9a77401356fac8b77fbf9f8180863ea4eeb924Phil Weaver NavigationBarFragment.this.updateAccessibilityServicesState(mAccessibilityManager); 105174922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt } 105274922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt } 105374922c63e1dfba074aa9219034e48a161bdfba5bCasey Burkhardt 105449fa016a98cef9940c883b3f620a0e90537a204eJason Monk private final Stub mRotationWatcher = new Stub() { 105549fa016a98cef9940c883b3f620a0e90537a204eJason Monk @Override 105690402957beb698799f65aa6756633554d121bc11Mike Digman public void onRotationChanged(final int rotation) throws RemoteException { 105749fa016a98cef9940c883b3f620a0e90537a204eJason Monk // We need this to be scheduled as early as possible to beat the redrawing of 105849fa016a98cef9940c883b3f620a0e90537a204eJason Monk // window in response to the orientation change. 105949fa016a98cef9940c883b3f620a0e90537a204eJason Monk Handler h = getView().getHandler(); 106049fa016a98cef9940c883b3f620a0e90537a204eJason Monk Message msg = Message.obtain(h, () -> { 106185ff7fa1687658d37c8701f45a534cb5866df077Mike Digman 106285ff7fa1687658d37c8701f45a534cb5866df077Mike Digman // If the screen rotation changes while locked, potentially update lock to flow with 106390402957beb698799f65aa6756633554d121bc11Mike Digman // new screen rotation and hide any showing suggestions. 106490402957beb698799f65aa6756633554d121bc11Mike Digman if (mRotationLockController.isRotationLocked()) { 106585ff7fa1687658d37c8701f45a534cb5866df077Mike Digman if (shouldOverrideUserLockPrefs(rotation)) { 106685ff7fa1687658d37c8701f45a534cb5866df077Mike Digman mRotationLockController.setRotationLockedAtAngle(true, rotation); 106785ff7fa1687658d37c8701f45a534cb5866df077Mike Digman } 10681e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman setRotateSuggestionButtonState(false, true); 106990402957beb698799f65aa6756633554d121bc11Mike Digman } 107090402957beb698799f65aa6756633554d121bc11Mike Digman 107149fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (mNavigationBarView != null 107249fa016a98cef9940c883b3f620a0e90537a204eJason Monk && mNavigationBarView.needsReorient(rotation)) { 107349fa016a98cef9940c883b3f620a0e90537a204eJason Monk repositionNavigationBar(); 107449fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 107549fa016a98cef9940c883b3f620a0e90537a204eJason Monk }); 107649fa016a98cef9940c883b3f620a0e90537a204eJason Monk msg.setAsynchronous(true); 107749fa016a98cef9940c883b3f620a0e90537a204eJason Monk h.sendMessageAtFrontOfQueue(msg); 107849fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 107985ff7fa1687658d37c8701f45a534cb5866df077Mike Digman 108085ff7fa1687658d37c8701f45a534cb5866df077Mike Digman private boolean shouldOverrideUserLockPrefs(final int rotation) { 1081ab65025833344b3b55bd146a86d48cabe254a89dMike Digman // Only override user prefs when returning to the natural rotation (normally portrait). 108285ff7fa1687658d37c8701f45a534cb5866df077Mike Digman // Don't let apps that force landscape or 180 alter user lock. 1083ab65025833344b3b55bd146a86d48cabe254a89dMike Digman return rotation == NATURAL_ROTATION; 108485ff7fa1687658d37c8701f45a534cb5866df077Mike Digman } 108549fa016a98cef9940c883b3f620a0e90537a204eJason Monk }; 108649fa016a98cef9940c883b3f620a0e90537a204eJason Monk 108749fa016a98cef9940c883b3f620a0e90537a204eJason Monk private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 108849fa016a98cef9940c883b3f620a0e90537a204eJason Monk @Override 108949fa016a98cef9940c883b3f620a0e90537a204eJason Monk public void onReceive(Context context, Intent intent) { 109049fa016a98cef9940c883b3f620a0e90537a204eJason Monk String action = intent.getAction(); 1091d002a0a96eb857804b3aafbcd32cf66a378c5b6cSiarhei Vishniakou if (Intent.ACTION_SCREEN_OFF.equals(action) 1092d002a0a96eb857804b3aafbcd32cf66a378c5b6cSiarhei Vishniakou || Intent.ACTION_SCREEN_ON.equals(action)) { 1093d002a0a96eb857804b3aafbcd32cf66a378c5b6cSiarhei Vishniakou notifyNavigationBarScreenOn(); 109449fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 1095a858c5f60f405621ee9b333c910084ec35150ceaPhil Weaver if (Intent.ACTION_USER_SWITCHED.equals(action)) { 1096a858c5f60f405621ee9b333c910084ec35150ceaPhil Weaver // The accessibility settings may be different for the new user 1097a858c5f60f405621ee9b333c910084ec35150ceaPhil Weaver updateAccessibilityServicesState(mAccessibilityManager); 1098a858c5f60f405621ee9b333c910084ec35150ceaPhil Weaver }; 109949fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 110049fa016a98cef9940c883b3f620a0e90537a204eJason Monk }; 110149fa016a98cef9940c883b3f620a0e90537a204eJason Monk 11027d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman class TaskStackListenerImpl extends SysUiTaskStackChangeListener { 11037d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman // Invalidate any rotation suggestion on task change or activity orientation change 11047d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman // Note: all callbacks happen on main thread 11057d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman 11067d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman @Override 11077d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman public void onTaskStackChanged() { 11081e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman setRotateSuggestionButtonState(false); 11097d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman } 11107d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman 11117d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman @Override 11127d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman public void onTaskRemoved(int taskId) { 11131e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman setRotateSuggestionButtonState(false); 11147d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman } 11157d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman 11167d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman @Override 11177d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman public void onTaskMovedToFront(int taskId) { 11181e28a5ae5031d1407cd2b55d5140ce336428a38bMike Digman setRotateSuggestionButtonState(false); 11197d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman } 11207d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman 11217d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman @Override 11227d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) { 112385a9bea67ad7c4199a95119af690eda5f9a06ce7Mike Digman // Only hide the icon if the top task changes its requestedOrientation 112485a9bea67ad7c4199a95119af690eda5f9a06ce7Mike Digman // Launcher can alter its requestedOrientation while it's not on top, don't hide on this 1125121b11ff5b80f1d9e762120f9cd87834b05a5b6aMike Digman Optional.ofNullable(ActivityManagerWrapper.getInstance()) 1126121b11ff5b80f1d9e762120f9cd87834b05a5b6aMike Digman .map(ActivityManagerWrapper::getRunningTask) 1127121b11ff5b80f1d9e762120f9cd87834b05a5b6aMike Digman .ifPresent(a -> { 1128121b11ff5b80f1d9e762120f9cd87834b05a5b6aMike Digman if (a.id == taskId) setRotateSuggestionButtonState(false); 1129121b11ff5b80f1d9e762120f9cd87834b05a5b6aMike Digman }); 11307d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman } 11317d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman } 11327d09277f99ca919db70d45425bd366ff1b1b7e0eMike Digman 11335075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman private class ViewRippler { 11345075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman private static final int RIPPLE_OFFSET_MS = 50; 11355075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman private static final int RIPPLE_INTERVAL_MS = 2000; 11365075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman private View mRoot; 11375075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman 11385075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman public void start(View root) { 11395075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman stop(); // Stop any pending ripple animations 11405075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman 11415075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman mRoot = root; 11425075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman 11435075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman // Schedule pending ripples, offset the 1st to avoid problems with visibility change 11445075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman mRoot.postOnAnimationDelayed(mRipple, RIPPLE_OFFSET_MS); 11455075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman mRoot.postOnAnimationDelayed(mRipple, RIPPLE_INTERVAL_MS); 11465075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman mRoot.postOnAnimationDelayed(mRipple, 2*RIPPLE_INTERVAL_MS); 1147c038c32c7c171e004f7cb74a4ab1d469a3b87f18Mike Digman mRoot.postOnAnimationDelayed(mRipple, 3*RIPPLE_INTERVAL_MS); 1148c038c32c7c171e004f7cb74a4ab1d469a3b87f18Mike Digman mRoot.postOnAnimationDelayed(mRipple, 4*RIPPLE_INTERVAL_MS); 11495075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman } 11505075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman 11515075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman public void stop() { 11525075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman if (mRoot != null) mRoot.removeCallbacks(mRipple); 11535075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman } 11545075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman 11555075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman private final Runnable mRipple = new Runnable() { 11565075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman @Override 11575075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman public void run() { // Cause the ripple to fire via false presses 1158f4c989962cd8accf027b1f10d4cbd51249886b33Mike Digman if (!mRoot.isAttachedToWindow()) return; 11595075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman mRoot.setPressed(true); 11605075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman mRoot.setPressed(false); 11615075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman } 11625075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman }; 11635075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman } 11645075264b6d0a9b2981713b6f65a4a65d2e9afce8Mike Digman 116549fa016a98cef9940c883b3f620a0e90537a204eJason Monk public static View create(Context context, FragmentListener listener) { 116649fa016a98cef9940c883b3f620a0e90537a204eJason Monk WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 116749fa016a98cef9940c883b3f620a0e90537a204eJason Monk LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT, 116849fa016a98cef9940c883b3f620a0e90537a204eJason Monk WindowManager.LayoutParams.TYPE_NAVIGATION_BAR, 116949fa016a98cef9940c883b3f620a0e90537a204eJason Monk WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING 117049fa016a98cef9940c883b3f620a0e90537a204eJason Monk | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 117149fa016a98cef9940c883b3f620a0e90537a204eJason Monk | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 117249fa016a98cef9940c883b3f620a0e90537a204eJason Monk | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 117349fa016a98cef9940c883b3f620a0e90537a204eJason Monk | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH 117449fa016a98cef9940c883b3f620a0e90537a204eJason Monk | WindowManager.LayoutParams.FLAG_SLIPPERY, 117549fa016a98cef9940c883b3f620a0e90537a204eJason Monk PixelFormat.TRANSLUCENT); 117649fa016a98cef9940c883b3f620a0e90537a204eJason Monk lp.token = new Binder(); 117749fa016a98cef9940c883b3f620a0e90537a204eJason Monk lp.setTitle("NavigationBar"); 11788583ae8a6af11bedbb00a4eb9efd2565da2fecbbPhil Weaver lp.accessibilityTitle = context.getString(R.string.nav_bar); 117949fa016a98cef9940c883b3f620a0e90537a204eJason Monk lp.windowAnimations = 0; 118049fa016a98cef9940c883b3f620a0e90537a204eJason Monk 118149fa016a98cef9940c883b3f620a0e90537a204eJason Monk View navigationBarView = LayoutInflater.from(context).inflate( 118249fa016a98cef9940c883b3f620a0e90537a204eJason Monk R.layout.navigation_bar_window, null); 118349fa016a98cef9940c883b3f620a0e90537a204eJason Monk 118449fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + navigationBarView); 118549fa016a98cef9940c883b3f620a0e90537a204eJason Monk if (navigationBarView == null) return null; 118649fa016a98cef9940c883b3f620a0e90537a204eJason Monk 118749fa016a98cef9940c883b3f620a0e90537a204eJason Monk context.getSystemService(WindowManager.class).addView(navigationBarView, lp); 118849fa016a98cef9940c883b3f620a0e90537a204eJason Monk FragmentHostManager fragmentHost = FragmentHostManager.get(navigationBarView); 118949fa016a98cef9940c883b3f620a0e90537a204eJason Monk NavigationBarFragment fragment = new NavigationBarFragment(); 119049fa016a98cef9940c883b3f620a0e90537a204eJason Monk fragmentHost.getFragmentManager().beginTransaction() 119149fa016a98cef9940c883b3f620a0e90537a204eJason Monk .replace(R.id.navigation_bar_frame, fragment, TAG) 119249fa016a98cef9940c883b3f620a0e90537a204eJason Monk .commit(); 119349fa016a98cef9940c883b3f620a0e90537a204eJason Monk fragmentHost.addTagListener(TAG, listener); 119449fa016a98cef9940c883b3f620a0e90537a204eJason Monk return navigationBarView; 119549fa016a98cef9940c883b3f620a0e90537a204eJason Monk } 119649fa016a98cef9940c883b3f620a0e90537a204eJason Monk} 1197