blob: 368b36bfd8e10e3424177ff9c26dc9d95f873a3d [file] [log] [blame]
Jason Monk49fa0162017-01-11 09:21:56 -05001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11 * KIND, either express or implied. See the License for the specific language governing
12 * permissions and limitations under the License.
13 */
14
15package com.android.systemui.statusbar.phone;
16
17import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
18import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
19import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
20import static android.app.StatusBarManager.windowStateToString;
21
22import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
Jason Monk2a6ea9c2017-01-26 11:14:51 -050023import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_WINDOW_STATE;
24import static com.android.systemui.statusbar.phone.StatusBar.dumpBarTransitions;
Jason Monk49fa0162017-01-11 09:21:56 -050025
Casey Burkhardt048c2bc2016-12-08 16:09:20 -080026import android.accessibilityservice.AccessibilityServiceInfo;
Mike Digman7d092772018-01-11 12:10:32 -080027import android.animation.Animator;
28import android.animation.AnimatorListenerAdapter;
Mike Digman7d092772018-01-11 12:10:32 -080029import android.animation.ObjectAnimator;
Jason Monk49fa0162017-01-11 09:21:56 -050030import android.annotation.Nullable;
31import android.app.ActivityManager;
32import android.app.ActivityManagerNative;
33import android.app.Fragment;
34import android.app.IActivityManager;
35import android.app.StatusBarManager;
36import android.content.BroadcastReceiver;
Casey Burkhardtb9dcd662017-03-20 15:10:16 -070037import android.content.ContentResolver;
Jason Monk49fa0162017-01-11 09:21:56 -050038import android.content.Context;
39import android.content.Intent;
40import android.content.IntentFilter;
41import android.content.res.Configuration;
Casey Burkhardt74922c62017-02-13 12:43:16 -080042import android.database.ContentObserver;
Jason Monk49fa0162017-01-11 09:21:56 -050043import android.graphics.PixelFormat;
44import android.graphics.Rect;
Mike Digman7d092772018-01-11 12:10:32 -080045import android.graphics.drawable.AnimatedVectorDrawable;
Jason Monk49fa0162017-01-11 09:21:56 -050046import android.inputmethodservice.InputMethodService;
47import android.os.Binder;
48import android.os.Bundle;
49import android.os.Handler;
50import android.os.IBinder;
51import android.os.Message;
Jason Monk49fa0162017-01-11 09:21:56 -050052import android.os.RemoteException;
53import android.os.UserHandle;
Casey Burkhardt74922c62017-02-13 12:43:16 -080054import android.provider.Settings;
Jason Monk865246d2017-01-19 08:27:01 -050055import android.support.annotation.VisibleForTesting;
Jason Monk49fa0162017-01-11 09:21:56 -050056import android.telecom.TelecomManager;
57import android.text.TextUtils;
58import android.util.Log;
59import android.view.IRotationWatcher.Stub;
60import android.view.KeyEvent;
61import android.view.LayoutInflater;
62import android.view.MotionEvent;
63import android.view.View;
64import android.view.ViewGroup;
65import android.view.WindowManager;
66import android.view.WindowManager.LayoutParams;
67import android.view.WindowManagerGlobal;
68import android.view.accessibility.AccessibilityEvent;
69import android.view.accessibility.AccessibilityManager;
Jason Monk91e587e2017-04-13 13:41:23 -040070import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
Jason Monk49fa0162017-01-11 09:21:56 -050071
72import com.android.internal.logging.MetricsLogger;
73import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Jason Monkea03be12017-12-04 11:08:41 -050074import com.android.internal.util.LatencyTracker;
Jason Monk9c7844c2017-01-18 15:21:53 -050075import com.android.systemui.Dependency;
Matthew Ngdc79e5c2017-12-14 17:37:35 -080076import com.android.systemui.OverviewProxyService;
Mike Digman7d092772018-01-11 12:10:32 -080077import com.android.systemui.Interpolators;
Jason Monk49fa0162017-01-11 09:21:56 -050078import com.android.systemui.R;
Jason Monk9c7844c2017-01-18 15:21:53 -050079import com.android.systemui.SysUiServiceProvider;
Jason Monk49fa0162017-01-11 09:21:56 -050080import com.android.systemui.assist.AssistManager;
81import com.android.systemui.fragments.FragmentHostManager;
82import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
83import com.android.systemui.recents.Recents;
Mike Digman7d092772018-01-11 12:10:32 -080084import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
85import com.android.systemui.shared.system.ActivityManagerWrapper;
Jason Monk49fa0162017-01-11 09:21:56 -050086import com.android.systemui.stackdivider.Divider;
87import com.android.systemui.statusbar.CommandQueue;
88import com.android.systemui.statusbar.CommandQueue.Callbacks;
Jason Monk91e587e2017-04-13 13:41:23 -040089import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
Mike Digman7d092772018-01-11 12:10:32 -080090import com.android.systemui.statusbar.policy.KeyButtonDrawable;
Jason Monk49fa0162017-01-11 09:21:56 -050091import com.android.systemui.statusbar.policy.KeyButtonView;
Mike Digman7d092772018-01-11 12:10:32 -080092import com.android.systemui.statusbar.policy.RotationLockController;
Jason Monk49fa0162017-01-11 09:21:56 -050093import com.android.systemui.statusbar.stack.StackStateAnimator;
94
95import java.io.FileDescriptor;
96import java.io.PrintWriter;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -080097import java.util.List;
Jason Monk49fa0162017-01-11 09:21:56 -050098import java.util.Locale;
99
100/**
101 * Fragment containing the NavigationBarFragment. Contains logic for what happens
102 * on clicks and view states of the nav bar.
103 */
104public class NavigationBarFragment extends Fragment implements Callbacks {
105
Jason Monkd4afe152017-05-01 15:37:43 -0400106 public static final String TAG = "NavigationBar";
Jason Monk49fa0162017-01-11 09:21:56 -0500107 private static final boolean DEBUG = false;
108 private static final String EXTRA_DISABLE_STATE = "disabled_state";
109
110 /** Allow some time inbetween the long press for back and recents. */
111 private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
112
Mike Digman90402952018-01-22 16:05:51 -0800113 private static final int BUTTON_FADE_IN_OUT_DURATION_MS = 100;
Mike Digman7d092772018-01-11 12:10:32 -0800114
Jason Monk49fa0162017-01-11 09:21:56 -0500115 protected NavigationBarView mNavigationBarView = null;
116 protected AssistManager mAssistManager;
117
118 private int mNavigationBarWindowState = WINDOW_STATE_SHOWING;
119
120 private int mNavigationIconHints = 0;
121 private int mNavigationBarMode;
Mike Digman90402952018-01-22 16:05:51 -0800122 private boolean mAccessibilityFeedbackEnabled;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800123 private AccessibilityManager mAccessibilityManager;
Casey Burkhardt74922c62017-02-13 12:43:16 -0800124 private MagnificationContentObserver mMagnificationObserver;
Casey Burkhardtb9dcd662017-03-20 15:10:16 -0700125 private ContentResolver mContentResolver;
Jason Monk49fa0162017-01-11 09:21:56 -0500126
127 private int mDisabledFlags1;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500128 private StatusBar mStatusBar;
Jason Monk49fa0162017-01-11 09:21:56 -0500129 private Recents mRecents;
130 private Divider mDivider;
131 private WindowManager mWindowManager;
132 private CommandQueue mCommandQueue;
133 private long mLastLockToAppLongPress;
134
135 private Locale mLocale;
136 private int mLayoutDirection;
137
138 private int mSystemUiVisibility;
139 private LightBarController mLightBarController;
Jason Monk49fa0162017-01-11 09:21:56 -0500140
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800141 private OverviewProxyService mOverviewProxyService;
142
Jason Monk49fa0162017-01-11 09:21:56 -0500143 public boolean mHomeBlockedThisTouch;
144
Mike Digman7d092772018-01-11 12:10:32 -0800145 private int mLastRotationSuggestion;
Mike Digman90402952018-01-22 16:05:51 -0800146 private boolean mHoveringRotationSuggestion;
Mike Digman7d092772018-01-11 12:10:32 -0800147 private RotationLockController mRotationLockController;
148 private TaskStackListenerImpl mTaskStackListener;
149
150 private final Runnable mRemoveRotationProposal = () -> setRotateSuggestionButtonState(false);
151 private Animator mRotateShowAnimator;
152 private Animator mRotateHideAnimator;
153
154
Jason Monk49fa0162017-01-11 09:21:56 -0500155 // ----- Fragment Lifecycle Callbacks -----
156
157 @Override
158 public void onCreate(@Nullable Bundle savedInstanceState) {
159 super.onCreate(savedInstanceState);
Jason Monk9c7844c2017-01-18 15:21:53 -0500160 mCommandQueue = SysUiServiceProvider.getComponent(getContext(), CommandQueue.class);
Jason Monk49fa0162017-01-11 09:21:56 -0500161 mCommandQueue.addCallbacks(this);
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500162 mStatusBar = SysUiServiceProvider.getComponent(getContext(), StatusBar.class);
Jason Monk9c7844c2017-01-18 15:21:53 -0500163 mRecents = SysUiServiceProvider.getComponent(getContext(), Recents.class);
164 mDivider = SysUiServiceProvider.getComponent(getContext(), Divider.class);
Jason Monk49fa0162017-01-11 09:21:56 -0500165 mWindowManager = getContext().getSystemService(WindowManager.class);
166 mAccessibilityManager = getContext().getSystemService(AccessibilityManager.class);
Jason Monk91e587e2017-04-13 13:41:23 -0400167 Dependency.get(AccessibilityManagerWrapper.class).addCallback(
168 mAccessibilityListener);
Casey Burkhardtb9dcd662017-03-20 15:10:16 -0700169 mContentResolver = getContext().getContentResolver();
Casey Burkhardt74922c62017-02-13 12:43:16 -0800170 mMagnificationObserver = new MagnificationContentObserver(
171 getContext().getMainThreadHandler());
Casey Burkhardtb9dcd662017-03-20 15:10:16 -0700172 mContentResolver.registerContentObserver(Settings.Secure.getUriFor(
Casey Burkhardt74922c62017-02-13 12:43:16 -0800173 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED), false,
Casey Burkhardt5d614402017-04-06 13:46:50 -0700174 mMagnificationObserver, UserHandle.USER_ALL);
Casey Burkhardt74922c62017-02-13 12:43:16 -0800175
Jason Monk49fa0162017-01-11 09:21:56 -0500176 if (savedInstanceState != null) {
177 mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0);
178 }
Jason Monk9c7844c2017-01-18 15:21:53 -0500179 mAssistManager = Dependency.get(AssistManager.class);
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800180 mOverviewProxyService = Dependency.get(OverviewProxyService.class);
Jason Monk49fa0162017-01-11 09:21:56 -0500181
182 try {
183 WindowManagerGlobal.getWindowManagerService()
Andrii Kulian35fa3c22017-03-11 09:37:28 -0800184 .watchRotation(mRotationWatcher, getContext().getDisplay().getDisplayId());
Jason Monk49fa0162017-01-11 09:21:56 -0500185 } catch (RemoteException e) {
186 throw e.rethrowFromSystemServer();
187 }
Mike Digman7d092772018-01-11 12:10:32 -0800188
189 mRotationLockController = Dependency.get(RotationLockController.class);
190
191 // Register the task stack listener
192 mTaskStackListener = new TaskStackListenerImpl();
193 ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
Jason Monk49fa0162017-01-11 09:21:56 -0500194 }
195
196 @Override
197 public void onDestroy() {
198 super.onDestroy();
199 mCommandQueue.removeCallbacks(this);
Jason Monk91e587e2017-04-13 13:41:23 -0400200 Dependency.get(AccessibilityManagerWrapper.class).removeCallback(
201 mAccessibilityListener);
Casey Burkhardtb9dcd662017-03-20 15:10:16 -0700202 mContentResolver.unregisterContentObserver(mMagnificationObserver);
Jason Monk49fa0162017-01-11 09:21:56 -0500203 try {
204 WindowManagerGlobal.getWindowManagerService()
205 .removeRotationWatcher(mRotationWatcher);
206 } catch (RemoteException e) {
207 throw e.rethrowFromSystemServer();
208 }
Mike Digman7d092772018-01-11 12:10:32 -0800209
210 // Unregister the task stack listener
211 ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTaskStackListener);
Jason Monk49fa0162017-01-11 09:21:56 -0500212 }
213
214 @Override
215 public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
216 Bundle savedInstanceState) {
217 return inflater.inflate(R.layout.navigation_bar, container, false);
218 }
219
220 @Override
221 public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
222 super.onViewCreated(view, savedInstanceState);
223 mNavigationBarView = (NavigationBarView) view;
224
225 mNavigationBarView.setDisabledFlags(mDisabledFlags1);
226 mNavigationBarView.setComponents(mRecents, mDivider);
227 mNavigationBarView.setOnVerticalChangedListener(this::onVerticalChanged);
228 mNavigationBarView.setOnTouchListener(this::onNavigationTouch);
229 if (savedInstanceState != null) {
230 mNavigationBarView.getLightTransitionsController().restoreState(savedInstanceState);
231 }
232
233 prepareNavigationBarView();
234 checkNavBarModes();
235
236 IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
237 filter.addAction(Intent.ACTION_SCREEN_ON);
238 getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
Siarhei Vishniakoud002a0a2017-06-05 22:44:37 +0100239 notifyNavigationBarScreenOn();
Jason Monk49fa0162017-01-11 09:21:56 -0500240 }
241
242 @Override
243 public void onDestroyView() {
244 super.onDestroyView();
Jason Monkaa573e92017-01-27 17:00:29 -0500245 mNavigationBarView.getLightTransitionsController().destroy(getContext());
Jason Monk49fa0162017-01-11 09:21:56 -0500246 getContext().unregisterReceiver(mBroadcastReceiver);
247 }
248
249 @Override
250 public void onSaveInstanceState(Bundle outState) {
251 super.onSaveInstanceState(outState);
252 outState.putInt(EXTRA_DISABLE_STATE, mDisabledFlags1);
253 if (mNavigationBarView != null) {
254 mNavigationBarView.getLightTransitionsController().saveState(outState);
255 }
256 }
257
258 @Override
259 public void onConfigurationChanged(Configuration newConfig) {
260 super.onConfigurationChanged(newConfig);
261 final Locale locale = getContext().getResources().getConfiguration().locale;
262 final int ld = TextUtils.getLayoutDirectionFromLocale(locale);
263 if (!locale.equals(mLocale) || ld != mLayoutDirection) {
264 if (DEBUG) {
265 Log.v(TAG, String.format(
266 "config changed locale/LD: %s (%d) -> %s (%d)", mLocale, mLayoutDirection,
267 locale, ld));
268 }
269 mLocale = locale;
270 mLayoutDirection = ld;
271 refreshLayout(ld);
272 }
273 repositionNavigationBar();
274 }
275
276 @Override
277 public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
278 if (mNavigationBarView != null) {
279 pw.print(" mNavigationBarWindowState=");
280 pw.println(windowStateToString(mNavigationBarWindowState));
281 pw.print(" mNavigationBarMode=");
282 pw.println(BarTransitions.modeToString(mNavigationBarMode));
283 dumpBarTransitions(pw, "mNavigationBarView", mNavigationBarView.getBarTransitions());
284 }
285
286 pw.print(" mNavigationBarView=");
287 if (mNavigationBarView == null) {
288 pw.println("null");
289 } else {
290 mNavigationBarView.dump(fd, pw, args);
291 }
292 }
293
294 // ----- CommandQueue Callbacks -----
295
296 @Override
297 public void setImeWindowStatus(IBinder token, int vis, int backDisposition,
298 boolean showImeSwitcher) {
299 boolean imeShown = (vis & InputMethodService.IME_VISIBLE) != 0;
300 int hints = mNavigationIconHints;
301 if ((backDisposition == InputMethodService.BACK_DISPOSITION_WILL_DISMISS) || imeShown) {
302 hints |= NAVIGATION_HINT_BACK_ALT;
303 } else {
304 hints &= ~NAVIGATION_HINT_BACK_ALT;
305 }
306 if (showImeSwitcher) {
307 hints |= NAVIGATION_HINT_IME_SHOWN;
308 } else {
309 hints &= ~NAVIGATION_HINT_IME_SHOWN;
310 }
311 if (hints == mNavigationIconHints) return;
312
313 mNavigationIconHints = hints;
314
315 if (mNavigationBarView != null) {
316 mNavigationBarView.setNavigationIconHints(hints);
317 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500318 mStatusBar.checkBarModes();
Jason Monk49fa0162017-01-11 09:21:56 -0500319 }
320
321 @Override
322 public void topAppWindowChanged(boolean showMenu) {
323 if (mNavigationBarView != null) {
324 mNavigationBarView.setMenuVisibility(showMenu);
325 }
326 }
327
328 @Override
329 public void setWindowState(int window, int state) {
330 if (mNavigationBarView != null
331 && window == StatusBarManager.WINDOW_NAVIGATION_BAR
332 && mNavigationBarWindowState != state) {
333 mNavigationBarWindowState = state;
334 if (DEBUG_WINDOW_STATE) Log.d(TAG, "Navigation bar " + windowStateToString(state));
335 }
336 }
337
Mike Digman7d092772018-01-11 12:10:32 -0800338 @Override
Mike Digmane0777312018-01-19 12:41:51 -0800339 public void onRotationProposal(final int rotation, boolean isValid) {
340 // This method will be called on rotation suggestion changes even if the proposed rotation
341 // is not valid for the top app. Use invalid rotation choices as a signal to remove the
342 // rotate button if shown.
343
344 if (!isValid) {
345 setRotateSuggestionButtonState(false);
346 return;
347 }
348
Mike Digman7d092772018-01-11 12:10:32 -0800349 if (rotation == mWindowManager.getDefaultDisplay().getRotation()) {
350 // Use this as a signal to remove any current suggestions
Mike Digman90402952018-01-22 16:05:51 -0800351 getView().getHandler().removeCallbacks(mRemoveRotationProposal);
Mike Digman7d092772018-01-11 12:10:32 -0800352 setRotateSuggestionButtonState(false);
353 } else {
354 mLastRotationSuggestion = rotation; // Remember rotation for click
355 setRotateSuggestionButtonState(true);
Mike Digman90402952018-01-22 16:05:51 -0800356 rescheduleRotationTimeout(false);
Mike Digman7d092772018-01-11 12:10:32 -0800357 }
358 }
359
Mike Digman90402952018-01-22 16:05:51 -0800360 private void rescheduleRotationTimeout(final boolean reasonHover) {
361 // May be called due to a new rotation proposal or a change in hover state
362 if (reasonHover) {
363 // Don't reschedule if a hide animator is running
364 if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) {
365 return;
366 }
367 // Don't reschedule if not visible
368 if (mNavigationBarView.getRotateSuggestionButton().getVisibility() != View.VISIBLE) {
369 return;
370 }
371 }
372
373 Handler h = getView().getHandler();
374 h.removeCallbacks(mRemoveRotationProposal); // Stop any pending removal
375 h.postDelayed(mRemoveRotationProposal,
376 computeRotationProposalTimeout()); // Schedule timeout
377 }
378
379 private int computeRotationProposalTimeout() {
380 if (mAccessibilityFeedbackEnabled) return 20000;
381 if (mHoveringRotationSuggestion) return 16000;
382 return 6000;
383 }
384
Mike Digman7d092772018-01-11 12:10:32 -0800385 public void setRotateSuggestionButtonState(final boolean visible) {
386 setRotateSuggestionButtonState(visible, false);
387 }
388
389 public void setRotateSuggestionButtonState(final boolean visible, final boolean skipAnim) {
390 ButtonDispatcher rotBtn = mNavigationBarView.getRotateSuggestionButton();
Mike Digman90402952018-01-22 16:05:51 -0800391 final boolean currentlyVisible = rotBtn.getVisibility() == View.VISIBLE;
Mike Digman7d092772018-01-11 12:10:32 -0800392
393 // Rerun a show animation to indicate change but don't rerun a hide animation
394 if (!visible && !currentlyVisible) return;
395
Mike Digman90402952018-01-22 16:05:51 -0800396 View currentView = rotBtn.getCurrentView();
Mike Digman7d092772018-01-11 12:10:32 -0800397 if (currentView == null) return;
398
Mike Digman90402952018-01-22 16:05:51 -0800399 KeyButtonDrawable kbd = rotBtn.getImageDrawable();
Mike Digman7d092772018-01-11 12:10:32 -0800400 if (kbd == null) return;
401
Mike Digman90402952018-01-22 16:05:51 -0800402 AnimatedVectorDrawable animIcon = null;
403 if (kbd.getDrawable(0) instanceof AnimatedVectorDrawable) {
404 animIcon = (AnimatedVectorDrawable) kbd.getDrawable(0);
405 }
406
Mike Digman7d092772018-01-11 12:10:32 -0800407 if (visible) { // Appear and change
408 rotBtn.setVisibility(View.VISIBLE);
Mike Digman90402952018-01-22 16:05:51 -0800409 mNavigationBarView.notifyAccessibilitySubtreeChanged();
Mike Digman7d092772018-01-11 12:10:32 -0800410
411 if (skipAnim) {
412 currentView.setAlpha(1f);
413 return;
414 }
415
416 // Start a new animation if running
417 if (mRotateShowAnimator != null) mRotateShowAnimator.pause();
418 if (mRotateHideAnimator != null) mRotateHideAnimator.pause();
419
420 ObjectAnimator appearFade = ObjectAnimator.ofFloat(currentView, "alpha",
421 0f, 1f);
Mike Digman90402952018-01-22 16:05:51 -0800422 appearFade.setDuration(BUTTON_FADE_IN_OUT_DURATION_MS);
Mike Digman7d092772018-01-11 12:10:32 -0800423 appearFade.setInterpolator(Interpolators.LINEAR);
424 mRotateShowAnimator = appearFade;
425 appearFade.start();
426
Mike Digman90402952018-01-22 16:05:51 -0800427 // Run the rotate icon's animation if it has one
428 if (animIcon != null) {
429 animIcon.reset();
430 animIcon.start();
431 }
432
Mike Digman7d092772018-01-11 12:10:32 -0800433 } else { // Hide
434
435 if (skipAnim) {
436 rotBtn.setVisibility(View.INVISIBLE);
Mike Digman90402952018-01-22 16:05:51 -0800437 mNavigationBarView.notifyAccessibilitySubtreeChanged();
Mike Digman7d092772018-01-11 12:10:32 -0800438 return;
439 }
440
441 // Don't start any new hide animations if one is running
442 if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) return;
443 // Pause any active show animations but don't reset the AVD to avoid jumps
444 if (mRotateShowAnimator != null) mRotateShowAnimator.pause();
445
446 ObjectAnimator fadeOut = ObjectAnimator.ofFloat(currentView, "alpha",
447 0f);
Mike Digman90402952018-01-22 16:05:51 -0800448 fadeOut.setDuration(BUTTON_FADE_IN_OUT_DURATION_MS);
Mike Digman7d092772018-01-11 12:10:32 -0800449 fadeOut.setInterpolator(Interpolators.LINEAR);
450 fadeOut.addListener(new AnimatorListenerAdapter() {
451 @Override
452 public void onAnimationEnd(Animator animation) {
453 rotBtn.setVisibility(View.INVISIBLE);
Mike Digman90402952018-01-22 16:05:51 -0800454 mNavigationBarView.notifyAccessibilitySubtreeChanged();
Mike Digman7d092772018-01-11 12:10:32 -0800455 }
456 });
457
458 mRotateHideAnimator = fadeOut;
459 fadeOut.start();
460 }
461 }
462
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500463 // Injected from StatusBar at creation.
Jason Monk49fa0162017-01-11 09:21:56 -0500464 public void setCurrentSysuiVisibility(int systemUiVisibility) {
465 mSystemUiVisibility = systemUiVisibility;
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500466 mNavigationBarMode = mStatusBar.computeBarMode(0, mSystemUiVisibility,
Jason Monk49fa0162017-01-11 09:21:56 -0500467 View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT,
468 View.NAVIGATION_BAR_TRANSPARENT);
469 checkNavBarModes();
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500470 mStatusBar.touchAutoHide();
Jason Monk49fa0162017-01-11 09:21:56 -0500471 mLightBarController.onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */,
472 true /* nbModeChanged */, mNavigationBarMode);
473 }
474
475 @Override
476 public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis,
477 int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) {
478 final int oldVal = mSystemUiVisibility;
479 final int newVal = (oldVal & ~mask) | (vis & mask);
480 final int diff = newVal ^ oldVal;
481 boolean nbModeChanged = false;
482 if (diff != 0) {
483 mSystemUiVisibility = newVal;
484
485 // update navigation bar mode
486 final int nbMode = getView() == null
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500487 ? -1 : mStatusBar.computeBarMode(oldVal, newVal,
Jason Monk49fa0162017-01-11 09:21:56 -0500488 View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT,
489 View.NAVIGATION_BAR_TRANSPARENT);
490 nbModeChanged = nbMode != -1;
491 if (nbModeChanged) {
492 if (mNavigationBarMode != nbMode) {
493 mNavigationBarMode = nbMode;
494 checkNavBarModes();
495 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500496 mStatusBar.touchAutoHide();
Jason Monk49fa0162017-01-11 09:21:56 -0500497 }
498 }
499
500 mLightBarController.onNavigationVisibilityChanged(vis, mask, nbModeChanged,
501 mNavigationBarMode);
502 }
503
504 @Override
505 public void disable(int state1, int state2, boolean animate) {
506 // All navigation bar flags are in state1.
507 int masked = state1 & (StatusBarManager.DISABLE_HOME
508 | StatusBarManager.DISABLE_RECENT
509 | StatusBarManager.DISABLE_BACK
510 | StatusBarManager.DISABLE_SEARCH);
511 if (masked != mDisabledFlags1) {
512 mDisabledFlags1 = masked;
513 if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state1);
514 }
515 }
516
517 // ----- Internal stuffz -----
518
519 private void refreshLayout(int layoutDirection) {
520 if (mNavigationBarView != null) {
521 mNavigationBarView.setLayoutDirection(layoutDirection);
522 }
523 }
524
525 private boolean shouldDisableNavbarGestures() {
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500526 return !mStatusBar.isDeviceProvisioned()
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800527 || (mDisabledFlags1 & StatusBarManager.DISABLE_SEARCH) != 0
528 || mOverviewProxyService.getProxy() != null;
Jason Monk49fa0162017-01-11 09:21:56 -0500529 }
530
531 private void repositionNavigationBar() {
532 if (mNavigationBarView == null || !mNavigationBarView.isAttachedToWindow()) return;
533
534 prepareNavigationBarView();
535
536 mWindowManager.updateViewLayout((View) mNavigationBarView.getParent(),
537 ((View) mNavigationBarView.getParent()).getLayoutParams());
538 }
539
Siarhei Vishniakoud002a0a2017-06-05 22:44:37 +0100540 private void notifyNavigationBarScreenOn() {
541 mNavigationBarView.notifyScreenOn();
Jason Monk49fa0162017-01-11 09:21:56 -0500542 }
543
544 private void prepareNavigationBarView() {
545 mNavigationBarView.reorient();
546
547 ButtonDispatcher recentsButton = mNavigationBarView.getRecentsButton();
548 recentsButton.setOnClickListener(this::onRecentsClick);
549 recentsButton.setOnTouchListener(this::onRecentsTouch);
550 recentsButton.setLongClickable(true);
551 recentsButton.setOnLongClickListener(this::onLongPressBackRecents);
552
553 ButtonDispatcher backButton = mNavigationBarView.getBackButton();
554 backButton.setLongClickable(true);
555 backButton.setOnLongClickListener(this::onLongPressBackRecents);
556
557 ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
558 homeButton.setOnTouchListener(this::onHomeTouch);
559 homeButton.setOnLongClickListener(this::onHomeLongClick);
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800560
561 ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton();
562 accessibilityButton.setOnClickListener(this::onAccessibilityClick);
563 accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick);
Phil Weaverdb9a7742017-04-18 08:15:06 -0700564 updateAccessibilityServicesState(mAccessibilityManager);
Mike Digman7d092772018-01-11 12:10:32 -0800565
566 ButtonDispatcher rotateSuggestionButton = mNavigationBarView.getRotateSuggestionButton();
567 rotateSuggestionButton.setOnClickListener(this::onRotateSuggestionClick);
Mike Digman90402952018-01-22 16:05:51 -0800568 rotateSuggestionButton.setOnHoverListener(this::onRotateSuggestionHover);
Jason Monk49fa0162017-01-11 09:21:56 -0500569 }
570
571 private boolean onHomeTouch(View v, MotionEvent event) {
572 if (mHomeBlockedThisTouch && event.getActionMasked() != MotionEvent.ACTION_DOWN) {
573 return true;
574 }
575 // If an incoming call is ringing, HOME is totally disabled.
576 // (The user is already on the InCallUI at this point,
577 // and his ONLY options are to answer or reject the call.)
578 switch (event.getAction()) {
579 case MotionEvent.ACTION_DOWN:
580 mHomeBlockedThisTouch = false;
581 TelecomManager telecomManager =
582 getContext().getSystemService(TelecomManager.class);
583 if (telecomManager != null && telecomManager.isRinging()) {
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500584 if (mStatusBar.isKeyguardShowing()) {
Jason Monk49fa0162017-01-11 09:21:56 -0500585 Log.i(TAG, "Ignoring HOME; there's a ringing incoming call. " +
586 "No heads up");
587 mHomeBlockedThisTouch = true;
588 return true;
589 }
590 }
591 break;
592 case MotionEvent.ACTION_UP:
593 case MotionEvent.ACTION_CANCEL:
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500594 mStatusBar.awakenDreams();
Jason Monk49fa0162017-01-11 09:21:56 -0500595 break;
596 }
597 return false;
598 }
599
600 private void onVerticalChanged(boolean isVertical) {
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500601 mStatusBar.setQsScrimEnabled(!isVertical);
Jason Monk49fa0162017-01-11 09:21:56 -0500602 }
603
604 private boolean onNavigationTouch(View v, MotionEvent event) {
Eliot Courtneycb5d3162017-08-09 16:53:15 +0900605 mStatusBar.checkUserAutohide(event);
Jason Monk49fa0162017-01-11 09:21:56 -0500606 return false;
607 }
608
Jason Monk865246d2017-01-19 08:27:01 -0500609 @VisibleForTesting
610 boolean onHomeLongClick(View v) {
Jason Monk49fa0162017-01-11 09:21:56 -0500611 if (shouldDisableNavbarGestures()) {
612 return false;
613 }
614 MetricsLogger.action(getContext(), MetricsEvent.ACTION_ASSIST_LONG_PRESS);
615 mAssistManager.startAssist(new Bundle() /* args */);
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500616 mStatusBar.awakenDreams();
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800617
Jason Monk49fa0162017-01-11 09:21:56 -0500618 if (mNavigationBarView != null) {
619 mNavigationBarView.abortCurrentGesture();
620 }
621 return true;
622 }
623
624 // additional optimization when we have software system buttons - start loading the recent
625 // tasks on touch down
626 private boolean onRecentsTouch(View v, MotionEvent event) {
627 int action = event.getAction() & MotionEvent.ACTION_MASK;
628 if (action == MotionEvent.ACTION_DOWN) {
629 mCommandQueue.preloadRecentApps();
630 } else if (action == MotionEvent.ACTION_CANCEL) {
631 mCommandQueue.cancelPreloadRecentApps();
632 } else if (action == MotionEvent.ACTION_UP) {
633 if (!v.isPressed()) {
634 mCommandQueue.cancelPreloadRecentApps();
635 }
636 }
637 return false;
638 }
639
640 private void onRecentsClick(View v) {
641 if (LatencyTracker.isEnabled(getContext())) {
642 LatencyTracker.getInstance(getContext()).onActionStart(
643 LatencyTracker.ACTION_TOGGLE_RECENTS);
644 }
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500645 mStatusBar.awakenDreams();
Jason Monk49fa0162017-01-11 09:21:56 -0500646 mCommandQueue.toggleRecentApps();
647 }
648
649 /**
650 * This handles long-press of both back and recents. They are
651 * handled together to capture them both being long-pressed
652 * at the same time to exit screen pinning (lock task).
653 *
654 * When accessibility mode is on, only a long-press from recents
655 * is required to exit.
656 *
657 * In all other circumstances we try to pass through long-press events
658 * for Back, so that apps can still use it. Which can be from two things.
659 * 1) Not currently in screen pinning (lock task).
660 * 2) Back is long-pressed without recents.
661 */
662 private boolean onLongPressBackRecents(View v) {
663 try {
664 boolean sendBackLongPress = false;
665 IActivityManager activityManager = ActivityManagerNative.getDefault();
666 boolean touchExplorationEnabled = mAccessibilityManager.isTouchExplorationEnabled();
667 boolean inLockTaskMode = activityManager.isInLockTaskMode();
668 if (inLockTaskMode && !touchExplorationEnabled) {
669 long time = System.currentTimeMillis();
670 // If we recently long-pressed the other button then they were
671 // long-pressed 'together'
672 if ((time - mLastLockToAppLongPress) < LOCK_TO_APP_GESTURE_TOLERENCE) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100673 activityManager.stopSystemLockTaskMode();
Jason Monk49fa0162017-01-11 09:21:56 -0500674 // When exiting refresh disabled flags.
675 mNavigationBarView.setDisabledFlags(mDisabledFlags1, true);
676 return true;
677 } else if ((v.getId() == R.id.back)
678 && !mNavigationBarView.getRecentsButton().getCurrentView().isPressed()) {
679 // If we aren't pressing recents right now then they presses
680 // won't be together, so send the standard long-press action.
681 sendBackLongPress = true;
682 }
683 mLastLockToAppLongPress = time;
684 } else {
685 // If this is back still need to handle sending the long-press event.
686 if (v.getId() == R.id.back) {
687 sendBackLongPress = true;
688 } else if (touchExplorationEnabled && inLockTaskMode) {
689 // When in accessibility mode a long press that is recents (not back)
690 // should stop lock task.
Benjamin Franza83859f2017-07-03 16:34:14 +0100691 activityManager.stopSystemLockTaskMode();
Jason Monk49fa0162017-01-11 09:21:56 -0500692 // When exiting refresh disabled flags.
693 mNavigationBarView.setDisabledFlags(mDisabledFlags1, true);
694 return true;
695 } else if (v.getId() == R.id.recent_apps) {
696 return onLongPressRecents();
697 }
698 }
699 if (sendBackLongPress) {
700 KeyButtonView keyButtonView = (KeyButtonView) v;
701 keyButtonView.sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
702 keyButtonView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
703 return true;
704 }
705 } catch (RemoteException e) {
706 Log.d(TAG, "Unable to reach activity manager", e);
707 }
708 return false;
709 }
710
711 private boolean onLongPressRecents() {
Erik Wolsheimer9be3a062017-05-31 14:59:57 -0700712 if (mRecents == null || !ActivityManager.supportsMultiWindow(getContext())
Matthew Ng43db6d22017-06-27 15:29:39 -0700713 || !mDivider.getView().getSnapAlgorithm().isSplitScreenFeasible()
714 || Recents.getConfiguration().isLowRamDevice) {
Jason Monk49fa0162017-01-11 09:21:56 -0500715 return false;
716 }
717
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500718 return mStatusBar.toggleSplitScreenMode(MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS,
Jason Monk49fa0162017-01-11 09:21:56 -0500719 MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS);
720 }
721
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800722 private void onAccessibilityClick(View v) {
723 mAccessibilityManager.notifyAccessibilityButtonClicked();
724 }
725
726 private boolean onAccessibilityLongClick(View v) {
Casey Burkhardt5e8b9802017-03-24 10:07:20 -0700727 Intent intent = new Intent(AccessibilityManager.ACTION_CHOOSE_ACCESSIBILITY_BUTTON);
728 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Casey Burkhardt5d614402017-04-06 13:46:50 -0700729 v.getContext().startActivityAsUser(intent, UserHandle.CURRENT);
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800730 return true;
731 }
732
Phil Weaverdb9a7742017-04-18 08:15:06 -0700733 private void updateAccessibilityServicesState(AccessibilityManager accessibilityManager) {
Casey Burkhardt74922c62017-02-13 12:43:16 -0800734 int requestingServices = 0;
735 try {
Casey Burkhardt5d614402017-04-06 13:46:50 -0700736 if (Settings.Secure.getIntForUser(mContentResolver,
737 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
738 UserHandle.USER_CURRENT) == 1) {
Casey Burkhardt74922c62017-02-13 12:43:16 -0800739 requestingServices++;
740 }
741 } catch (Settings.SettingNotFoundException e) {
742 }
743
Mike Digman90402952018-01-22 16:05:51 -0800744 boolean feedbackEnabled = false;
Casey Burkhardt5d614402017-04-06 13:46:50 -0700745 // AccessibilityManagerService resolves services for the current user since the local
746 // AccessibilityManager is created from a Context with the INTERACT_ACROSS_USERS permission
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800747 final List<AccessibilityServiceInfo> services =
Phil Weaverdb9a7742017-04-18 08:15:06 -0700748 accessibilityManager.getEnabledAccessibilityServiceList(
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800749 AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800750 for (int i = services.size() - 1; i >= 0; --i) {
751 AccessibilityServiceInfo info = services.get(i);
752 if ((info.flags & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0) {
753 requestingServices++;
754 }
Mike Digman90402952018-01-22 16:05:51 -0800755
756 if (info.feedbackType != 0 && info.feedbackType !=
757 AccessibilityServiceInfo.FEEDBACK_GENERIC) {
758 feedbackEnabled = true;
759 }
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800760 }
761
Mike Digman90402952018-01-22 16:05:51 -0800762 mAccessibilityFeedbackEnabled = feedbackEnabled;
763
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800764 final boolean showAccessibilityButton = requestingServices >= 1;
765 final boolean targetSelection = requestingServices >= 2;
766 mNavigationBarView.setAccessibilityButtonState(showAccessibilityButton, targetSelection);
767 }
768
Mike Digman7d092772018-01-11 12:10:32 -0800769 private void onRotateSuggestionClick(View v) {
770 mRotationLockController.setRotationLockedAtAngle(true, mLastRotationSuggestion);
771 }
772
Mike Digman90402952018-01-22 16:05:51 -0800773 private boolean onRotateSuggestionHover(View v, MotionEvent event) {
774 final int action = event.getActionMasked();
775 mHoveringRotationSuggestion = (action == MotionEvent.ACTION_HOVER_ENTER)
776 || (action == MotionEvent.ACTION_HOVER_MOVE);
777 rescheduleRotationTimeout(true);
778 return false; // Must return false so a11y hover events are dispatched correctly.
779 }
780
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500781 // ----- Methods that StatusBar talks to (should be minimized) -----
Jason Monk49fa0162017-01-11 09:21:56 -0500782
Jason Monk49fa0162017-01-11 09:21:56 -0500783 public void setLightBarController(LightBarController lightBarController) {
784 mLightBarController = lightBarController;
785 mLightBarController.setNavigationBar(mNavigationBarView.getLightTransitionsController());
786 }
787
788 public boolean isSemiTransparent() {
789 return mNavigationBarMode == MODE_SEMI_TRANSPARENT;
790 }
791
Jason Monk49fa0162017-01-11 09:21:56 -0500792 public void disableAnimationsDuringHide(long delay) {
793 mNavigationBarView.setLayoutTransitionsEnabled(false);
794 mNavigationBarView.postDelayed(() -> mNavigationBarView.setLayoutTransitionsEnabled(true),
795 delay + StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
796 }
797
Jason Monk49fa0162017-01-11 09:21:56 -0500798 public BarTransitions getBarTransitions() {
799 return mNavigationBarView.getBarTransitions();
800 }
801
802 public void checkNavBarModes() {
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500803 mStatusBar.checkBarMode(mNavigationBarMode,
Jason Monk49fa0162017-01-11 09:21:56 -0500804 mNavigationBarWindowState, mNavigationBarView.getBarTransitions());
805 }
806
807 public void finishBarAnimations() {
808 mNavigationBarView.getBarTransitions().finishAnimations();
809 }
810
Jason Monk91e587e2017-04-13 13:41:23 -0400811 private final AccessibilityServicesStateChangeListener mAccessibilityListener =
812 this::updateAccessibilityServicesState;
813
Casey Burkhardt74922c62017-02-13 12:43:16 -0800814 private class MagnificationContentObserver extends ContentObserver {
815
816 public MagnificationContentObserver(Handler handler) {
817 super(handler);
818 }
819
820 @Override
821 public void onChange(boolean selfChange) {
Phil Weaverdb9a7742017-04-18 08:15:06 -0700822 NavigationBarFragment.this.updateAccessibilityServicesState(mAccessibilityManager);
Casey Burkhardt74922c62017-02-13 12:43:16 -0800823 }
824 }
825
Jason Monk49fa0162017-01-11 09:21:56 -0500826 private final Stub mRotationWatcher = new Stub() {
827 @Override
Mike Digman90402952018-01-22 16:05:51 -0800828 public void onRotationChanged(final int rotation) throws RemoteException {
Jason Monk49fa0162017-01-11 09:21:56 -0500829 // We need this to be scheduled as early as possible to beat the redrawing of
830 // window in response to the orientation change.
831 Handler h = getView().getHandler();
832 Message msg = Message.obtain(h, () -> {
Mike Digman90402952018-01-22 16:05:51 -0800833 // If the screen rotation changes while locked, update lock rotation to flow with
834 // new screen rotation and hide any showing suggestions.
835 if (mRotationLockController.isRotationLocked()) {
836 mRotationLockController.setRotationLockedAtAngle(true, rotation);
837 setRotateSuggestionButtonState(false, true);
838 }
839
Jason Monk49fa0162017-01-11 09:21:56 -0500840 if (mNavigationBarView != null
841 && mNavigationBarView.needsReorient(rotation)) {
842 repositionNavigationBar();
843 }
844 });
845 msg.setAsynchronous(true);
846 h.sendMessageAtFrontOfQueue(msg);
847 }
848 };
849
850 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
851 @Override
852 public void onReceive(Context context, Intent intent) {
853 String action = intent.getAction();
Siarhei Vishniakoud002a0a2017-06-05 22:44:37 +0100854 if (Intent.ACTION_SCREEN_OFF.equals(action)
855 || Intent.ACTION_SCREEN_ON.equals(action)) {
856 notifyNavigationBarScreenOn();
Jason Monk49fa0162017-01-11 09:21:56 -0500857 }
858 }
859 };
860
Mike Digman7d092772018-01-11 12:10:32 -0800861 class TaskStackListenerImpl extends SysUiTaskStackChangeListener {
862 // Invalidate any rotation suggestion on task change or activity orientation change
863 // Note: all callbacks happen on main thread
864
865 @Override
866 public void onTaskStackChanged() {
867 setRotateSuggestionButtonState(false);
868 }
869
870 @Override
871 public void onTaskRemoved(int taskId) {
872 setRotateSuggestionButtonState(false);
873 }
874
875 @Override
876 public void onTaskMovedToFront(int taskId) {
877 setRotateSuggestionButtonState(false);
878 }
879
880 @Override
881 public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) {
882 setRotateSuggestionButtonState(false);
883 }
884 }
885
Jason Monk49fa0162017-01-11 09:21:56 -0500886 public static View create(Context context, FragmentListener listener) {
887 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
888 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
889 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
890 WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
891 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
892 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
893 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
894 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
895 | WindowManager.LayoutParams.FLAG_SLIPPERY,
896 PixelFormat.TRANSLUCENT);
897 lp.token = new Binder();
Jason Monk49fa0162017-01-11 09:21:56 -0500898 lp.setTitle("NavigationBar");
899 lp.windowAnimations = 0;
900
901 View navigationBarView = LayoutInflater.from(context).inflate(
902 R.layout.navigation_bar_window, null);
903
904 if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + navigationBarView);
905 if (navigationBarView == null) return null;
906
907 context.getSystemService(WindowManager.class).addView(navigationBarView, lp);
908 FragmentHostManager fragmentHost = FragmentHostManager.get(navigationBarView);
909 NavigationBarFragment fragment = new NavigationBarFragment();
910 fragmentHost.getFragmentManager().beginTransaction()
911 .replace(R.id.navigation_bar_frame, fragment, TAG)
912 .commit();
913 fragmentHost.addTagListener(TAG, listener);
914 return navigationBarView;
915 }
916}