diff --git a/packages/SystemUI/res/layout/navigation_bar_window.xml b/packages/SystemUI/res/layout/navigation_bar_window.xml
new file mode 100644
index 0000000000000..051bf3ac3faf8
--- /dev/null
+++ b/packages/SystemUI/res/layout/navigation_bar_window.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
diff --git a/packages/SystemUI/src/com/android/systemui/SysUiServiceProvider.java b/packages/SystemUI/src/com/android/systemui/SysUiServiceProvider.java
new file mode 100644
index 0000000000000..c4470cd846718
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SysUiServiceProvider.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui;
+
+/**
+ * The interface for getting core components of SysUI. Exists for Testability
+ * since tests don't have SystemUIApplication as their ApplicationContext.
+ */
+public interface SysUiServiceProvider {
+ T getComponent(Class interfaceType);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUI.java b/packages/SystemUI/src/com/android/systemui/SystemUI.java
index f30baee35f3a2..6b30a89d51c01 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUI.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUI.java
@@ -25,7 +25,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Map;
-public abstract class SystemUI {
+public abstract class SystemUI implements SysUiServiceProvider {
public Context mContext;
public Map, Object> mComponents;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 19880230186ae..bd4e3dcbbd486 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -55,7 +55,7 @@ import java.util.Map;
/**
* Application class for SystemUI.
*/
-public class SystemUIApplication extends Application {
+public class SystemUIApplication extends Application implements SysUiServiceProvider {
private static final String TAG = "SystemUIService";
private static final boolean DEBUG = false;
@@ -239,4 +239,8 @@ public class SystemUIApplication extends Application {
public SystemUI[] getServices() {
return mServices;
}
+
+ public static T getComponent(Context context, Class interfaceType) {
+ return ((SysUiServiceProvider) context.getApplicationContext()).getComponent(interfaceType);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 6d0e77c061320..57857ccb8cc68 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -52,7 +52,7 @@ public class FragmentHostManager {
private FragmentLifecycleCallbacks mLifecycleCallbacks;
FragmentHostManager(Context context, FragmentService manager, View rootView) {
- mContext = PluginManager.getInstance(context).getAllPluginContext(context);
+ mContext = context;
mManager = manager;
mRootView = rootView;
mConfigChanges.applyNewConfig(context.getResources());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index db099bc15472f..561b46984ff04 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -185,9 +185,6 @@ public abstract class BaseStatusBar extends SystemUI implements
protected int mLayoutDirection = -1; // invalid
protected AccessibilityManager mAccessibilityManager;
- // on-screen navigation buttons
- protected NavigationBarView mNavigationBarView = null;
-
protected boolean mDeviceInteractive;
protected boolean mVisible;
@@ -238,8 +235,6 @@ public abstract class BaseStatusBar extends SystemUI implements
protected WindowManager mWindowManager;
protected IWindowManager mWindowManagerService;
- protected abstract void refreshLayout(int layoutDirection);
-
protected Display mDisplay;
private boolean mDeviceProvisioned = false;
@@ -945,8 +940,6 @@ public abstract class BaseStatusBar extends SystemUI implements
@Override
protected void onConfigurationChanged(Configuration newConfig) {
- final Locale locale = mContext.getResources().getConfiguration().locale;
- final int ld = TextUtils.getLayoutDirectionFromLocale(locale);
final float fontScale = newConfig.fontScale;
final int density = newConfig.densityDpi;
if (density != mDensity || mFontScale != fontScale) {
@@ -954,16 +947,6 @@ public abstract class BaseStatusBar extends SystemUI implements
mDensity = density;
mFontScale = fontScale;
}
- if (! locale.equals(mLocale) || ld != mLayoutDirection) {
- if (DEBUG) {
- Log.v(TAG, String.format(
- "config changed locale/LD: %s (%d) -> %s (%d)", mLocale, mLayoutDirection,
- locale, ld));
- }
- mLocale = locale;
- mLayoutDirection = ld;
- refreshLayout(ld);
- }
}
protected void onDensityOrFontScaleChanged() {
@@ -1285,26 +1268,6 @@ public abstract class BaseStatusBar extends SystemUI implements
protected abstract View getStatusBarView();
- protected View.OnTouchListener mRecentsPreloadOnTouchListener = new View.OnTouchListener() {
- // additional optimization when we have software system buttons - start loading the recent
- // tasks on touch down
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- int action = event.getAction() & MotionEvent.ACTION_MASK;
- if (action == MotionEvent.ACTION_DOWN) {
- preloadRecents();
- } else if (action == MotionEvent.ACTION_CANCEL) {
- cancelPreloadingRecents();
- } else if (action == MotionEvent.ACTION_UP) {
- if (!v.isPressed()) {
- cancelPreloadingRecents();
- }
-
- }
- return false;
- }
- };
-
/**
* Toggle docking the app window
*
@@ -2256,7 +2219,6 @@ public abstract class BaseStatusBar extends SystemUI implements
protected abstract void setAreThereNotifications();
protected abstract void updateNotifications();
- public abstract boolean shouldDisableNavbarGestures();
public abstract void addNotification(StatusBarNotification notification,
RankingMap ranking, Entry oldEntry);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index a3e4d5b6db542..fed28e32b0bb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -32,6 +32,8 @@ import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.SystemUI;
+import java.util.ArrayList;
+
/**
* This class takes the functions from IStatusBar that come in on
* binder pool threads and posts messages to get them onto the main
@@ -91,7 +93,7 @@ public class CommandQueue extends IStatusBar.Stub {
private static final String SHOW_IME_SWITCHER_KEY = "showImeSwitcherKey";
private final Object mLock = new Object();
- private Callbacks[] mCallbacks = new Callbacks[0];
+ private ArrayList mCallbacks = new ArrayList<>();
private Handler mHandler = new H(Looper.getMainLooper());
/**
@@ -144,15 +146,11 @@ public class CommandQueue extends IStatusBar.Stub {
}
public void addCallbacks(Callbacks callbacks) {
- Callbacks[] newArray = new Callbacks[mCallbacks.length + 1];
- for (int i = 0; i < newArray.length - 1; i++) {
- newArray[i] = mCallbacks[i];
- if (newArray[i] == callbacks) {
- throw new IllegalArgumentException("Callback was already added");
- }
- }
- newArray[newArray.length - 1] = callbacks;
- mCallbacks = newArray;
+ mCallbacks.add(callbacks);
+ }
+
+ public void removeCallbacks(Callbacks callbacks) {
+ mCallbacks.remove(callbacks);
}
public void setIcon(String slot, StatusBarIcon icon) {
@@ -427,182 +425,182 @@ public class CommandQueue extends IStatusBar.Stub {
switch (msg.arg1) {
case OP_SET_ICON: {
Pair p = (Pair) msg.obj;
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].setIcon(p.first, p.second);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).setIcon(p.first, p.second);
}
break;
}
case OP_REMOVE_ICON:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].removeIcon((String) msg.obj);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).removeIcon((String) msg.obj);
}
break;
}
break;
}
case MSG_DISABLE:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].disable(msg.arg1, msg.arg2, true /* animate */);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).disable(msg.arg1, msg.arg2, true /* animate */);
}
break;
case MSG_EXPAND_NOTIFICATIONS:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].animateExpandNotificationsPanel();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).animateExpandNotificationsPanel();
}
break;
case MSG_COLLAPSE_PANELS:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].animateCollapsePanels(0);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).animateCollapsePanels(0);
}
break;
case MSG_EXPAND_SETTINGS:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].animateExpandSettingsPanel((String) msg.obj);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).animateExpandSettingsPanel((String) msg.obj);
}
break;
case MSG_SET_SYSTEMUI_VISIBILITY:
SomeArgs args = (SomeArgs) msg.obj;
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].setSystemUiVisibility(args.argi1, args.argi2, args.argi3,
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).setSystemUiVisibility(args.argi1, args.argi2, args.argi3,
args.argi4, (Rect) args.arg1, (Rect) args.arg2);
}
args.recycle();
break;
case MSG_TOP_APP_WINDOW_CHANGED:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].topAppWindowChanged(msg.arg1 != 0);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).topAppWindowChanged(msg.arg1 != 0);
}
break;
case MSG_SHOW_IME_BUTTON:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].setImeWindowStatus((IBinder) msg.obj, msg.arg1, msg.arg2,
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).setImeWindowStatus((IBinder) msg.obj, msg.arg1, msg.arg2,
msg.getData().getBoolean(SHOW_IME_SWITCHER_KEY, false));
}
break;
case MSG_SHOW_RECENT_APPS:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].showRecentApps(msg.arg1 != 0, msg.arg2 != 0);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).showRecentApps(msg.arg1 != 0, msg.arg2 != 0);
}
break;
case MSG_HIDE_RECENT_APPS:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].hideRecentApps(msg.arg1 != 0, msg.arg2 != 0);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).hideRecentApps(msg.arg1 != 0, msg.arg2 != 0);
}
break;
case MSG_TOGGLE_RECENT_APPS:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].toggleRecentApps();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).toggleRecentApps();
}
break;
case MSG_PRELOAD_RECENT_APPS:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].preloadRecentApps();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).preloadRecentApps();
}
break;
case MSG_CANCEL_PRELOAD_RECENT_APPS:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].cancelPreloadRecentApps();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).cancelPreloadRecentApps();
}
break;
case MSG_DISMISS_KEYBOARD_SHORTCUTS:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].dismissKeyboardShortcutsMenu();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).dismissKeyboardShortcutsMenu();
}
break;
case MSG_TOGGLE_KEYBOARD_SHORTCUTS:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].toggleKeyboardShortcutsMenu(msg.arg1);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).toggleKeyboardShortcutsMenu(msg.arg1);
}
break;
case MSG_SET_WINDOW_STATE:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].setWindowState(msg.arg1, msg.arg2);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).setWindowState(msg.arg1, msg.arg2);
}
break;
case MSG_BUZZ_BEEP_BLINKED:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].buzzBeepBlinked();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).buzzBeepBlinked();
}
break;
case MSG_NOTIFICATION_LIGHT_OFF:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].notificationLightOff();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).notificationLightOff();
}
break;
case MSG_NOTIFICATION_LIGHT_PULSE:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].notificationLightPulse((Integer) msg.obj, msg.arg1, msg.arg2);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).notificationLightPulse((Integer) msg.obj, msg.arg1, msg.arg2);
}
break;
case MSG_SHOW_SCREEN_PIN_REQUEST:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].showScreenPinningRequest(msg.arg1);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).showScreenPinningRequest(msg.arg1);
}
break;
case MSG_APP_TRANSITION_PENDING:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].appTransitionPending();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).appTransitionPending();
}
break;
case MSG_APP_TRANSITION_CANCELLED:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].appTransitionCancelled();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).appTransitionCancelled();
}
break;
case MSG_APP_TRANSITION_STARTING:
- for (int i = 0; i < mCallbacks.length; i++) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
Pair data = (Pair) msg.obj;
- mCallbacks[i].appTransitionStarting(data.first, data.second);
+ mCallbacks.get(i).appTransitionStarting(data.first, data.second);
}
break;
case MSG_APP_TRANSITION_FINISHED:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].appTransitionFinished();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).appTransitionFinished();
}
break;
case MSG_ASSIST_DISCLOSURE:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].showAssistDisclosure();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).showAssistDisclosure();
}
break;
case MSG_START_ASSIST:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].startAssist((Bundle) msg.obj);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).startAssist((Bundle) msg.obj);
}
break;
case MSG_CAMERA_LAUNCH_GESTURE:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].onCameraLaunchGestureDetected(msg.arg1);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).onCameraLaunchGestureDetected(msg.arg1);
}
break;
case MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].showTvPictureInPictureMenu();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).showTvPictureInPictureMenu();
}
break;
case MSG_ADD_QS_TILE:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].addQsTile((ComponentName) msg.obj);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).addQsTile((ComponentName) msg.obj);
}
break;
case MSG_REMOVE_QS_TILE:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].remQsTile((ComponentName) msg.obj);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).remQsTile((ComponentName) msg.obj);
}
break;
case MSG_CLICK_QS_TILE:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].clickTile((ComponentName) msg.obj);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).clickTile((ComponentName) msg.obj);
}
break;
case MSG_TOGGLE_APP_SPLIT_SCREEN:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].toggleSplitScreen();
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).toggleSplitScreen();
}
break;
case MSG_HANDLE_SYSNAV_KEY:
- for (int i = 0; i < mCallbacks.length; i++) {
- mCallbacks[i].handleSystemNavigationKey(msg.arg1);
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).handleSystemNavigationKey(msg.arg1);
}
break;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index dd5832b886ee3..7adb36d615d1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -64,6 +64,7 @@ public class CarStatusBar extends PhoneStatusBar implements
private ConnectedDeviceSignalController mConnectedDeviceSignalController;
private View mSignalsView;
+ private CarNavigationBarView mNavigationBarView;
@Override
public void start() {
@@ -121,7 +122,17 @@ public class CarStatusBar extends PhoneStatusBar implements
}
@Override
- protected void addNavigationBar() {
+ protected void createNavigationBar() {
+ if (mNavigationBarView != null) {
+ return;
+ }
+
+ mCarNavigationBar =
+ (CarNavigationBarView) View.inflate(mContext, R.layout.car_navigation_bar, null);
+ mController = new CarNavigationBarController(mContext, mCarNavigationBar,
+ this /* ActivityStarter*/);
+ mNavigationBarView = mCarNavigationBar;
+ mCarNavigationBar.getBarTransitions().setAlwaysOpaque(true);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
@@ -137,19 +148,6 @@ public class CarStatusBar extends PhoneStatusBar implements
mWindowManager.addView(mNavigationBarView, lp);
}
- @Override
- protected void createNavigationBarView(Context context) {
- if (mNavigationBarView != null) {
- return;
- }
- mCarNavigationBar =
- (CarNavigationBarView) View.inflate(context, R.layout.car_navigation_bar, null);
- mController = new CarNavigationBarController(context, mCarNavigationBar,
- this /* ActivityStarter*/);
- mNavigationBarView = mCarNavigationBar;
- mCarNavigationBar.getBarTransitions().setAlwaysOpaque(true);
- }
-
@Override
public void showBatteryView() {
if (Log.isLoggable(TAG, Log.DEBUG)) {
@@ -191,12 +189,6 @@ public class CarStatusBar extends PhoneStatusBar implements
mContext.registerReceiver(mPackageChangeReceiver, filter);
}
- @Override
- protected void repositionNavigationBar() {
- // The navigation bar for a vehicle will not need to be repositioned, as it is always
- // set at the bottom.
- }
-
public boolean hasDockedTask() {
return Recents.getSystemServices().hasDockedTask();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index b5358a187d5a3..6dddf1832f6cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -34,8 +34,8 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
private final StatusBarIconController mStatusBarIconController;
private final BatteryController mBatteryController;
private FingerprintUnlockController mFingerprintUnlockController;
- private final NavigationBarView mNavigationBarView;
+ private LightBarTransitionsController mNavigationBarController;
private int mSystemUiVisibility;
private int mFullscreenStackVisibility;
private int mDockedStackVisibility;
@@ -50,22 +50,24 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
private final Rect mLastDockedBounds = new Rect();
public LightBarController(StatusBarIconController statusBarIconController,
- NavigationBarView navigationBarView,
BatteryController batteryController) {
mStatusBarIconController = statusBarIconController;
- mNavigationBarView = navigationBarView;
mBatteryController = batteryController;
batteryController.addCallback(this);
}
+ public void setNavigationBar(LightBarTransitionsController navigationBar) {
+ mNavigationBarController = navigationBar;
+ }
+
public void setFingerprintUnlockController(
FingerprintUnlockController fingerprintUnlockController) {
mFingerprintUnlockController = fingerprintUnlockController;
}
- public void onSystemUiVisibilityChanged(int vis, int fullscreenStackVis, int dockedStackVis,
+ public void onSystemUiVisibilityChanged(int fullscreenStackVis, int dockedStackVis,
int mask, Rect fullscreenStackBounds, Rect dockedStackBounds, boolean sbModeChanged,
- int statusBarMode, boolean nbModeChanged, int navigationBarMode) {
+ int statusBarMode) {
int oldFullscreen = mFullscreenStackVisibility;
int newFullscreen = (oldFullscreen & ~mask) | (fullscreenStackVis & mask);
int diffFullscreen = newFullscreen ^ oldFullscreen;
@@ -84,6 +86,15 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
updateStatus(fullscreenStackBounds, dockedStackBounds);
}
+ mFullscreenStackVisibility = newFullscreen;
+ mDockedStackVisibility = newDocked;
+ mLastStatusBarMode = statusBarMode;
+ mLastFullscreenBounds.set(fullscreenStackBounds);
+ mLastDockedBounds.set(dockedStackBounds);
+ }
+
+ public void onNavigationVisibilityChanged(int vis, int mask, boolean nbModeChanged,
+ int navigationBarMode) {
int oldVis = mSystemUiVisibility;
int newVis = (oldVis & ~mask) | (vis & mask);
int diffVis = newVis ^ oldVis;
@@ -95,19 +106,15 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
updateNavigation();
}
}
- mFullscreenStackVisibility = newFullscreen;
- mDockedStackVisibility = newDocked;
mSystemUiVisibility = newVis;
- mLastStatusBarMode = statusBarMode;
mLastNavigationBarMode = navigationBarMode;
- mLastFullscreenBounds.set(fullscreenStackBounds);
- mLastDockedBounds.set(dockedStackBounds);
}
private void reevaluate() {
- onSystemUiVisibilityChanged(mSystemUiVisibility, mFullscreenStackVisibility,
+ onSystemUiVisibilityChanged(mFullscreenStackVisibility,
mDockedStackVisibility, 0 /* mask */, mLastFullscreenBounds, mLastDockedBounds,
- true /* sbModeChange*/, mLastStatusBarMode, true /* nbModeChange*/,
+ true /* sbModeChange*/, mLastStatusBarMode);
+ onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */, true /* nbModeChanged */,
mLastNavigationBarMode);
}
@@ -169,8 +176,8 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
}
private void updateNavigation() {
- if (mNavigationBarView != null) {
- mNavigationBarView.getLightTransitionsController().setIconsDark(
+ if (mNavigationBarController != null) {
+ mNavigationBarController.setIconsDark(
mNavigationLight, animateChange());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index 1d4d2d1c7bf0f..0f9f0563b7fea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone;
import android.animation.ValueAnimator;
+import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
@@ -28,6 +29,7 @@ import com.android.systemui.Interpolators;
public class LightBarTransitionsController {
public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
+ private static final String EXTRA_DARK_INTENSITY = "dark_intensity";
private final Handler mHandler;
private final DarkIntensityApplier mApplier;
@@ -40,6 +42,7 @@ public class LightBarTransitionsController {
private float mPendingDarkIntensity;
private ValueAnimator mTintAnimator;
private float mDarkIntensity;
+ private float mNextDarkIntensity;
private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
@Override
@@ -53,6 +56,16 @@ public class LightBarTransitionsController {
mHandler = new Handler();
}
+ public void saveState(Bundle outState) {
+ float intensity = mTintAnimator != null && mTintAnimator.isRunning()
+ ? mNextDarkIntensity : mDarkIntensity;
+ outState.putFloat(EXTRA_DARK_INTENSITY, intensity);
+ }
+
+ public void restoreState(Bundle savedInstanceState) {
+ setIconTintInternal(savedInstanceState.getFloat(EXTRA_DARK_INTENSITY, 0));
+ }
+
public void appTransitionPending() {
mTransitionPending = true;
}
@@ -119,6 +132,7 @@ public class LightBarTransitionsController {
if (mDarkIntensity == targetDarkIntensity) {
return;
}
+ mNextDarkIntensity = targetDarkIntensity;
mTintAnimator = ValueAnimator.ofFloat(mDarkIntensity, targetDarkIntensity);
mTintAnimator.addUpdateListener(
animation -> setIconTintInternal((Float) animation.getAnimatedValue()));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
new file mode 100644
index 0000000000000..c0f245c10af6e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -0,0 +1,666 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
+import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
+import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
+import static android.app.StatusBarManager.windowStateToString;
+
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
+import static com.android.systemui.statusbar.phone.PhoneStatusBar.DEBUG_WINDOW_STATE;
+import static com.android.systemui.statusbar.phone.PhoneStatusBar.dumpBarTransitions;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.app.Fragment;
+import android.app.IActivityManager;
+import android.app.StatusBarManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.inputmethodservice.InputMethodService;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.telecom.TelecomManager;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.IRotationWatcher.Stub;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.keyguard.LatencyTracker;
+import com.android.systemui.R;
+import com.android.systemui.SystemUIApplication;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.fragments.FragmentHostManager;
+import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.CommandQueue.Callbacks;
+import com.android.systemui.statusbar.policy.KeyButtonView;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Locale;
+
+/**
+ * Fragment containing the NavigationBarFragment. Contains logic for what happens
+ * on clicks and view states of the nav bar.
+ */
+public class NavigationBarFragment extends Fragment implements Callbacks {
+
+ private static final String TAG = "NavigationBar";
+ private static final boolean DEBUG = false;
+ private static final String EXTRA_DISABLE_STATE = "disabled_state";
+
+ /** Allow some time inbetween the long press for back and recents. */
+ private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200;
+
+ protected NavigationBarView mNavigationBarView = null;
+ protected AssistManager mAssistManager;
+
+ private int mNavigationBarWindowState = WINDOW_STATE_SHOWING;
+
+ private int mNavigationIconHints = 0;
+ private int mNavigationBarMode;
+ protected AccessibilityManager mAccessibilityManager;
+
+ private int mDisabledFlags1;
+ private PhoneStatusBar mPhoneStatusBar;
+ private Recents mRecents;
+ private Divider mDivider;
+ private WindowManager mWindowManager;
+ private CommandQueue mCommandQueue;
+ private long mLastLockToAppLongPress;
+
+ private Locale mLocale;
+ private int mLayoutDirection;
+
+ private int mSystemUiVisibility;
+ private LightBarController mLightBarController;
+ private boolean mKeyguardGoingAway;
+
+ public boolean mHomeBlockedThisTouch;
+
+ // ----- Fragment Lifecycle Callbacks -----
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mCommandQueue = SystemUIApplication.getComponent(getContext(), CommandQueue.class);
+ mCommandQueue.addCallbacks(this);
+ mPhoneStatusBar = SystemUIApplication.getComponent(getContext(), PhoneStatusBar.class);
+ mRecents = SystemUIApplication.getComponent(getContext(), Recents.class);
+ mDivider = SystemUIApplication.getComponent(getContext(), Divider.class);
+ mWindowManager = getContext().getSystemService(WindowManager.class);
+ mAccessibilityManager = getContext().getSystemService(AccessibilityManager.class);
+ if (savedInstanceState != null) {
+ mDisabledFlags1 = savedInstanceState.getInt(EXTRA_DISABLE_STATE, 0);
+ }
+
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .watchRotation(mRotationWatcher);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ mCommandQueue.removeCallbacks(this);
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .removeRotationWatcher(mRotationWatcher);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.navigation_bar, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ mNavigationBarView = (NavigationBarView) view;
+
+ mNavigationBarView.setDisabledFlags(mDisabledFlags1);
+ mNavigationBarView.setComponents(mRecents, mDivider);
+ mNavigationBarView.setOnVerticalChangedListener(this::onVerticalChanged);
+ mNavigationBarView.setOnTouchListener(this::onNavigationTouch);
+ if (savedInstanceState != null) {
+ mNavigationBarView.getLightTransitionsController().restoreState(savedInstanceState);
+ }
+
+ prepareNavigationBarView();
+ checkNavBarModes();
+
+ IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_SCREEN_ON);
+ getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
+ PowerManager pm = getContext().getSystemService(PowerManager.class);
+ notifyNavigationBarScreenOn(pm.isScreenOn());
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ getContext().unregisterReceiver(mBroadcastReceiver);
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(EXTRA_DISABLE_STATE, mDisabledFlags1);
+ if (mNavigationBarView != null) {
+ mNavigationBarView.getLightTransitionsController().saveState(outState);
+ }
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ final Locale locale = getContext().getResources().getConfiguration().locale;
+ final int ld = TextUtils.getLayoutDirectionFromLocale(locale);
+ if (!locale.equals(mLocale) || ld != mLayoutDirection) {
+ if (DEBUG) {
+ Log.v(TAG, String.format(
+ "config changed locale/LD: %s (%d) -> %s (%d)", mLocale, mLayoutDirection,
+ locale, ld));
+ }
+ mLocale = locale;
+ mLayoutDirection = ld;
+ refreshLayout(ld);
+ }
+ repositionNavigationBar();
+ }
+
+ @Override
+ public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mNavigationBarView != null) {
+ pw.print(" mNavigationBarWindowState=");
+ pw.println(windowStateToString(mNavigationBarWindowState));
+ pw.print(" mNavigationBarMode=");
+ pw.println(BarTransitions.modeToString(mNavigationBarMode));
+ dumpBarTransitions(pw, "mNavigationBarView", mNavigationBarView.getBarTransitions());
+ }
+
+ pw.print(" mNavigationBarView=");
+ if (mNavigationBarView == null) {
+ pw.println("null");
+ } else {
+ mNavigationBarView.dump(fd, pw, args);
+ }
+ }
+
+ // ----- CommandQueue Callbacks -----
+
+ @Override
+ public void setImeWindowStatus(IBinder token, int vis, int backDisposition,
+ boolean showImeSwitcher) {
+ boolean imeShown = (vis & InputMethodService.IME_VISIBLE) != 0;
+ int hints = mNavigationIconHints;
+ if ((backDisposition == InputMethodService.BACK_DISPOSITION_WILL_DISMISS) || imeShown) {
+ hints |= NAVIGATION_HINT_BACK_ALT;
+ } else {
+ hints &= ~NAVIGATION_HINT_BACK_ALT;
+ }
+ if (showImeSwitcher) {
+ hints |= NAVIGATION_HINT_IME_SHOWN;
+ } else {
+ hints &= ~NAVIGATION_HINT_IME_SHOWN;
+ }
+ if (hints == mNavigationIconHints) return;
+
+ mNavigationIconHints = hints;
+
+ if (mNavigationBarView != null) {
+ mNavigationBarView.setNavigationIconHints(hints);
+ }
+ mPhoneStatusBar.checkBarModes();
+ }
+
+ @Override
+ public void topAppWindowChanged(boolean showMenu) {
+ if (mNavigationBarView != null) {
+ mNavigationBarView.setMenuVisibility(showMenu);
+ }
+ }
+
+ @Override
+ public void setWindowState(int window, int state) {
+ if (mNavigationBarView != null
+ && window == StatusBarManager.WINDOW_NAVIGATION_BAR
+ && mNavigationBarWindowState != state) {
+ mNavigationBarWindowState = state;
+ if (DEBUG_WINDOW_STATE) Log.d(TAG, "Navigation bar " + windowStateToString(state));
+ }
+ }
+
+ @Override
+ public void appTransitionPending() {
+ mNavigationBarView.getLightTransitionsController().appTransitionPending();
+ }
+
+ @Override
+ public void appTransitionCancelled() {
+ mNavigationBarView.getLightTransitionsController().appTransitionCancelled();
+ }
+
+ @Override
+ public void appTransitionStarting(long startTime, long duration) {
+ if (mKeyguardGoingAway) return;
+ doAppTransitionStarting(startTime, duration);
+ }
+
+ /**
+ * Calls appTransitionStarting for the nav bar regardless of whether keyguard is going away.
+ * public so PhoneStatusBar can force this when needed.
+ */
+ public void doAppTransitionStarting(long startTime, long duration) {
+ mNavigationBarView.getLightTransitionsController().appTransitionStarting(startTime,
+ duration);
+ }
+
+ // Injected from PhoneStatusBar at creation.
+ public void setCurrentSysuiVisibility(int systemUiVisibility) {
+ mSystemUiVisibility = systemUiVisibility;
+ mNavigationBarMode = mPhoneStatusBar.computeBarMode(0, mSystemUiVisibility,
+ View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT,
+ View.NAVIGATION_BAR_TRANSPARENT);
+ checkNavBarModes();
+ mPhoneStatusBar.touchAutoHide();
+ mLightBarController.onNavigationVisibilityChanged(mSystemUiVisibility, 0 /* mask */,
+ true /* nbModeChanged */, mNavigationBarMode);
+ }
+
+ @Override
+ public void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis,
+ int mask, Rect fullscreenStackBounds, Rect dockedStackBounds) {
+ final int oldVal = mSystemUiVisibility;
+ final int newVal = (oldVal & ~mask) | (vis & mask);
+ final int diff = newVal ^ oldVal;
+ boolean nbModeChanged = false;
+ if (diff != 0) {
+ mSystemUiVisibility = newVal;
+
+ // update navigation bar mode
+ final int nbMode = getView() == null
+ ? -1 : mPhoneStatusBar.computeBarMode(oldVal, newVal,
+ View.NAVIGATION_BAR_TRANSIENT, View.NAVIGATION_BAR_TRANSLUCENT,
+ View.NAVIGATION_BAR_TRANSPARENT);
+ nbModeChanged = nbMode != -1;
+ if (nbModeChanged) {
+ if (mNavigationBarMode != nbMode) {
+ mNavigationBarMode = nbMode;
+ checkNavBarModes();
+ }
+ mPhoneStatusBar.touchAutoHide();
+ }
+ }
+
+ mLightBarController.onNavigationVisibilityChanged(vis, mask, nbModeChanged,
+ mNavigationBarMode);
+ }
+
+ @Override
+ public void disable(int state1, int state2, boolean animate) {
+ // All navigation bar flags are in state1.
+ int masked = state1 & (StatusBarManager.DISABLE_HOME
+ | StatusBarManager.DISABLE_RECENT
+ | StatusBarManager.DISABLE_BACK
+ | StatusBarManager.DISABLE_SEARCH);
+ if (masked != mDisabledFlags1) {
+ mDisabledFlags1 = masked;
+ if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state1);
+ }
+ }
+
+ // ----- Internal stuffz -----
+
+ private void refreshLayout(int layoutDirection) {
+ if (mNavigationBarView != null) {
+ mNavigationBarView.setLayoutDirection(layoutDirection);
+ }
+ }
+
+ private boolean shouldDisableNavbarGestures() {
+ return !mPhoneStatusBar.isDeviceProvisioned()
+ || (mDisabledFlags1 & StatusBarManager.DISABLE_SEARCH) != 0;
+ }
+
+ private void repositionNavigationBar() {
+ if (mNavigationBarView == null || !mNavigationBarView.isAttachedToWindow()) return;
+
+ prepareNavigationBarView();
+
+ mWindowManager.updateViewLayout((View) mNavigationBarView.getParent(),
+ ((View) mNavigationBarView.getParent()).getLayoutParams());
+ }
+
+ private void notifyNavigationBarScreenOn(boolean screenOn) {
+ mNavigationBarView.notifyScreenOn(screenOn);
+ }
+
+ private void prepareNavigationBarView() {
+ mNavigationBarView.reorient();
+
+ ButtonDispatcher recentsButton = mNavigationBarView.getRecentsButton();
+ recentsButton.setOnClickListener(this::onRecentsClick);
+ recentsButton.setOnTouchListener(this::onRecentsTouch);
+ recentsButton.setLongClickable(true);
+ recentsButton.setOnLongClickListener(this::onLongPressBackRecents);
+
+ ButtonDispatcher backButton = mNavigationBarView.getBackButton();
+ backButton.setLongClickable(true);
+ backButton.setOnLongClickListener(this::onLongPressBackRecents);
+
+ ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
+ homeButton.setOnTouchListener(this::onHomeTouch);
+ homeButton.setOnLongClickListener(this::onHomeLongClick);
+
+ if (mAssistManager != null) {
+ mAssistManager.onConfigurationChanged();
+ }
+ }
+
+ private boolean onHomeTouch(View v, MotionEvent event) {
+ if (mHomeBlockedThisTouch && event.getActionMasked() != MotionEvent.ACTION_DOWN) {
+ return true;
+ }
+ // If an incoming call is ringing, HOME is totally disabled.
+ // (The user is already on the InCallUI at this point,
+ // and his ONLY options are to answer or reject the call.)
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mHomeBlockedThisTouch = false;
+ TelecomManager telecomManager =
+ getContext().getSystemService(TelecomManager.class);
+ if (telecomManager != null && telecomManager.isRinging()) {
+ if (mPhoneStatusBar.isKeyguardShowing()) {
+ Log.i(TAG, "Ignoring HOME; there's a ringing incoming call. " +
+ "No heads up");
+ mHomeBlockedThisTouch = true;
+ return true;
+ }
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ mPhoneStatusBar.awakenDreams();
+ break;
+ }
+ return false;
+ }
+
+ private void onVerticalChanged(boolean isVertical) {
+ if (mAssistManager != null) {
+ // TODO: Clean this up.
+ mAssistManager.onConfigurationChanged();
+ }
+ mPhoneStatusBar.setQsScrimEnabled(!isVertical);
+ }
+
+ private boolean onNavigationTouch(View v, MotionEvent event) {
+ mPhoneStatusBar.checkUserAutohide(v, event);
+ return false;
+ }
+
+ private boolean onHomeLongClick(View v) {
+ if (shouldDisableNavbarGestures()) {
+ return false;
+ }
+ MetricsLogger.action(getContext(), MetricsEvent.ACTION_ASSIST_LONG_PRESS);
+ mAssistManager.startAssist(new Bundle() /* args */);
+ mPhoneStatusBar.awakenDreams();
+ if (mNavigationBarView != null) {
+ mNavigationBarView.abortCurrentGesture();
+ }
+ return true;
+ }
+
+ // additional optimization when we have software system buttons - start loading the recent
+ // tasks on touch down
+ private boolean onRecentsTouch(View v, MotionEvent event) {
+ int action = event.getAction() & MotionEvent.ACTION_MASK;
+ if (action == MotionEvent.ACTION_DOWN) {
+ mCommandQueue.preloadRecentApps();
+ } else if (action == MotionEvent.ACTION_CANCEL) {
+ mCommandQueue.cancelPreloadRecentApps();
+ } else if (action == MotionEvent.ACTION_UP) {
+ if (!v.isPressed()) {
+ mCommandQueue.cancelPreloadRecentApps();
+ }
+ }
+ return false;
+ }
+
+ private void onRecentsClick(View v) {
+ if (LatencyTracker.isEnabled(getContext())) {
+ LatencyTracker.getInstance(getContext()).onActionStart(
+ LatencyTracker.ACTION_TOGGLE_RECENTS);
+ }
+ mPhoneStatusBar.awakenDreams();
+ mCommandQueue.toggleRecentApps();
+ }
+
+ /**
+ * This handles long-press of both back and recents. They are
+ * handled together to capture them both being long-pressed
+ * at the same time to exit screen pinning (lock task).
+ *
+ * When accessibility mode is on, only a long-press from recents
+ * is required to exit.
+ *
+ * In all other circumstances we try to pass through long-press events
+ * for Back, so that apps can still use it. Which can be from two things.
+ * 1) Not currently in screen pinning (lock task).
+ * 2) Back is long-pressed without recents.
+ */
+ private boolean onLongPressBackRecents(View v) {
+ try {
+ boolean sendBackLongPress = false;
+ IActivityManager activityManager = ActivityManagerNative.getDefault();
+ boolean touchExplorationEnabled = mAccessibilityManager.isTouchExplorationEnabled();
+ boolean inLockTaskMode = activityManager.isInLockTaskMode();
+ if (inLockTaskMode && !touchExplorationEnabled) {
+ long time = System.currentTimeMillis();
+ // If we recently long-pressed the other button then they were
+ // long-pressed 'together'
+ if ((time - mLastLockToAppLongPress) < LOCK_TO_APP_GESTURE_TOLERENCE) {
+ activityManager.stopLockTaskMode();
+ // When exiting refresh disabled flags.
+ mNavigationBarView.setDisabledFlags(mDisabledFlags1, true);
+ return true;
+ } else if ((v.getId() == R.id.back)
+ && !mNavigationBarView.getRecentsButton().getCurrentView().isPressed()) {
+ // If we aren't pressing recents right now then they presses
+ // won't be together, so send the standard long-press action.
+ sendBackLongPress = true;
+ }
+ mLastLockToAppLongPress = time;
+ } else {
+ // If this is back still need to handle sending the long-press event.
+ if (v.getId() == R.id.back) {
+ sendBackLongPress = true;
+ } else if (touchExplorationEnabled && inLockTaskMode) {
+ // When in accessibility mode a long press that is recents (not back)
+ // should stop lock task.
+ activityManager.stopLockTaskMode();
+ // When exiting refresh disabled flags.
+ mNavigationBarView.setDisabledFlags(mDisabledFlags1, true);
+ return true;
+ } else if (v.getId() == R.id.recent_apps) {
+ return onLongPressRecents();
+ }
+ }
+ if (sendBackLongPress) {
+ KeyButtonView keyButtonView = (KeyButtonView) v;
+ keyButtonView.sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.FLAG_LONG_PRESS);
+ keyButtonView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
+ return true;
+ }
+ } catch (RemoteException e) {
+ Log.d(TAG, "Unable to reach activity manager", e);
+ }
+ return false;
+ }
+
+ private boolean onLongPressRecents() {
+ if (mRecents == null || !ActivityManager.supportsMultiWindow()
+ || !mDivider.getView().getSnapAlgorithm()
+ .isSplitScreenFeasible()) {
+ return false;
+ }
+
+ return mPhoneStatusBar.toggleSplitScreenMode(MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS,
+ MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS);
+ }
+
+ // ----- Methods that PhoneStatusBar talks to (should be minimized) -----
+
+ public void setAssistManager(AssistManager assistManager) {
+ mAssistManager = assistManager;
+ }
+
+ public void setLightBarController(LightBarController lightBarController) {
+ mLightBarController = lightBarController;
+ mLightBarController.setNavigationBar(mNavigationBarView.getLightTransitionsController());
+ }
+
+ public boolean isSemiTransparent() {
+ return mNavigationBarMode == MODE_SEMI_TRANSPARENT;
+ }
+
+ public void onKeyguardOccludedChanged(boolean keyguardOccluded) {
+ mNavigationBarView.onKeyguardOccludedChanged(keyguardOccluded);
+ }
+
+ public void disableAnimationsDuringHide(long delay) {
+ mNavigationBarView.setLayoutTransitionsEnabled(false);
+ mNavigationBarView.postDelayed(() -> mNavigationBarView.setLayoutTransitionsEnabled(true),
+ delay + StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
+ }
+
+ public void setKeyguardGoingAway(boolean keyguardGoingAway) {
+ mKeyguardGoingAway = keyguardGoingAway;
+ }
+
+ public BarTransitions getBarTransitions() {
+ return mNavigationBarView.getBarTransitions();
+ }
+
+ public void checkNavBarModes() {
+ mPhoneStatusBar.checkBarMode(mNavigationBarMode,
+ mNavigationBarWindowState, mNavigationBarView.getBarTransitions());
+ }
+
+ public void finishBarAnimations() {
+ mNavigationBarView.getBarTransitions().finishAnimations();
+ }
+
+ private final Stub mRotationWatcher = new Stub() {
+ @Override
+ public void onRotationChanged(int rotation) throws RemoteException {
+ // We need this to be scheduled as early as possible to beat the redrawing of
+ // window in response to the orientation change.
+ Handler h = getView().getHandler();
+ Message msg = Message.obtain(h, () -> {
+ if (mNavigationBarView != null
+ && mNavigationBarView.needsReorient(rotation)) {
+ repositionNavigationBar();
+ }
+ });
+ msg.setAsynchronous(true);
+ h.sendMessageAtFrontOfQueue(msg);
+ }
+ };
+
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (Intent.ACTION_SCREEN_OFF.equals(action)) {
+ notifyNavigationBarScreenOn(false);
+ } else if (Intent.ACTION_SCREEN_ON.equals(action)) {
+ notifyNavigationBarScreenOn(true);
+ }
+ }
+ };
+
+ public static View create(Context context, FragmentListener listener) {
+ WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+ LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
+ WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+ | WindowManager.LayoutParams.FLAG_SLIPPERY,
+ PixelFormat.TRANSLUCENT);
+ lp.token = new Binder();
+ // this will allow the navbar to run in an overlay on devices that support this
+ if (ActivityManager.isHighEndGfx()) {
+ lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+ }
+ lp.setTitle("NavigationBar");
+ lp.windowAnimations = 0;
+
+ View navigationBarView = LayoutInflater.from(context).inflate(
+ R.layout.navigation_bar_window, null);
+
+ if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + navigationBarView);
+ if (navigationBarView == null) return null;
+
+ context.getSystemService(WindowManager.class).addView(navigationBarView, lp);
+ FragmentHostManager fragmentHost = FragmentHostManager.get(navigationBarView);
+ NavigationBarFragment fragment = new NavigationBarFragment();
+ fragmentHost.getFragmentManager().beginTransaction()
+ .replace(R.id.navigation_bar_frame, fragment, TAG)
+ .commit();
+ fragmentHost.addTagListener(TAG, listener);
+ return navigationBarView;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index b2b093cf0033a..b6feb0eba058b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -70,7 +70,6 @@ public class NavigationBarInflaterView extends FrameLayout
protected LayoutInflater mLayoutInflater;
protected LayoutInflater mLandscapeInflater;
- private int mDensity;
protected FrameLayout mRot0;
protected FrameLayout mRot90;
@@ -86,7 +85,6 @@ public class NavigationBarInflaterView extends FrameLayout
public NavigationBarInflaterView(Context context, AttributeSet attrs) {
super(context, attrs);
- mDensity = context.getResources().getConfiguration().densityDpi;
createInflaters();
Display display = ((WindowManager)
context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
@@ -102,18 +100,6 @@ public class NavigationBarInflaterView extends FrameLayout
mLandscapeInflater = LayoutInflater.from(mContext.createConfigurationContext(landscape));
}
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- if (mDensity != newConfig.densityDpi) {
- mDensity = newConfig.densityDpi;
- createInflaters();
- inflateChildren();
- clearViews();
- inflateLayout(mCurrentLayout);
- }
- }
-
@Override
protected void onFinishInflate() {
super.onFinishInflate();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index d22f42144fddb..31c78c8f911de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -434,7 +434,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener