Work on separating out the status bar management
Lots of stuff:
- Make StatusBarIconController be a permanent dependency
- Break out dark stuff into DarkIconDispatcher
- Create StatusBarFragment
- This bit is a bit ugly for now, but will be better later
- Other stuff probably
Test: runtest systemui
Change-Id: I4973bc9f944e66af92731bf1edd2b39657f1782f
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 63af3e0..c6452c0 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -21,6 +21,8 @@
<com.android.systemui.statusbar.phone.PhoneStatusBarView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/status_bar_height"
android:id="@+id/status_bar"
android:background="@drawable/system_bar_background"
android:orientation="vertical"
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index c2686f8..51eefb6 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -59,9 +59,10 @@
sysui:ignoreRightInset="true"
android:importantForAccessibility="no"/>
- <include layout="@layout/status_bar"
+ <FrameLayout
+ android:id="@+id/status_bar_container"
android:layout_width="match_parent"
- android:layout_height="@dimen/status_bar_height" />
+ android:layout_height="wrap_content" />
<include layout="@layout/brightness_mirror" />
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 29a8da0..69e3874 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -16,18 +16,29 @@
package com.android.systemui;
import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.graphics.Rect;
import android.util.ArraySet;
import android.util.AttributeSet;
+import android.util.TypedValue;
import android.view.View;
import android.widget.ImageView;
+import android.widget.LinearLayout;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
public class BatteryMeterView extends ImageView implements
- BatteryController.BatteryStateChangeCallback, TunerService.Tunable {
+ BatteryStateChangeCallback, Tunable, DarkReceiver, ConfigurationListener {
private final BatteryMeterDrawable mDrawable;
private final String mSlotBattery;
@@ -77,6 +88,7 @@
mBatteryController.addCallback(this);
mDrawable.startListening();
Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
+ Dependency.get(ConfigurationController.class).addCallback(this);
}
@Override
@@ -85,6 +97,7 @@
mBatteryController.removeCallback(this);
mDrawable.stopListening();
Dependency.get(TunerService.class).removeTunable(this);
+ Dependency.get(ConfigurationController.class).removeCallback(this);
}
@Override
@@ -99,8 +112,35 @@
}
- public void setDarkIntensity(float f) {
- mDrawable.setDarkIntensity(f);
+ @Override
+ public void onDensityOrFontScaleChanged() {
+ scaleBatteryMeterViews();
+ }
+
+ /**
+ * Looks up the scale factor for status bar icons and scales the battery view by that amount.
+ */
+ private void scaleBatteryMeterViews() {
+ Resources res = getContext().getResources();
+ TypedValue typedValue = new TypedValue();
+
+ res.getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true);
+ float iconScaleFactor = typedValue.getFloat();
+
+ int batteryHeight = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_height);
+ int batteryWidth = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_width);
+ int marginBottom = res.getDimensionPixelSize(R.dimen.battery_margin_bottom);
+
+ LinearLayout.LayoutParams scaledLayoutParams = new LinearLayout.LayoutParams(
+ (int) (batteryWidth * iconScaleFactor), (int) (batteryHeight * iconScaleFactor));
+ scaledLayoutParams.setMarginsRelative(0, 0, 0, marginBottom);
+
+ setLayoutParams(scaledLayoutParams);
+ }
+
+ @Override
+ public void onDarkChanged(Rect area, float darkIntensity, int tint) {
+ mDrawable.setDarkIntensity(DarkIconDispatcher.isInArea(area, this) ? darkIntensity : 0);
}
public void setRawColors(int fgColor, int bgColor) {
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 7066a1b..1d4a093 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -25,9 +25,13 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.plugins.PluginManager;
+import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
+import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
import com.android.systemui.statusbar.phone.StatusBarWindowManager;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryControllerImpl;
@@ -35,6 +39,8 @@
import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastControllerImpl;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
@@ -187,6 +193,15 @@
mProviders.put(StatusBarWindowManager.class.getName(), () ->
new StatusBarWindowManager(mContext));
+ mProviders.put(DarkIconDispatcher.class.getName(), () ->
+ new DarkIconDispatcherImpl(mContext));
+
+ mProviders.put(ConfigurationController.class.getName(), () ->
+ new ConfigurationControllerImpl(mContext));
+
+ mProviders.put(StatusBarIconController.class.getName(), () ->
+ new StatusBarIconControllerImpl(mContext));
+
// Put all dependencies above here so the factory can override them if it wants.
SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
}
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 50506a9..0c6bf52 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -97,7 +97,7 @@
return p;
}
- public void addTagListener(String tag, FragmentListener listener) {
+ public FragmentHostManager addTagListener(String tag, FragmentListener listener) {
ArrayList<FragmentListener> listeners = mListeners.get(tag);
if (listeners == null) {
listeners = new ArrayList<>();
@@ -108,6 +108,7 @@
if (current != null && current.getView() != null) {
listener.onFragmentViewCreated(tag, current);
}
+ return this;
}
// Shouldn't generally be needed, included for completeness sake.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index a4cd14d..b48b829 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -179,7 +179,7 @@
}
@Override
- public void onKeyguardChanged() {
+ public void onKeyguardShowingChanged() {
refreshState();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 5374f18..423a1df 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -141,7 +141,7 @@
}
@Override
- public void onKeyguardChanged() {
+ public void onKeyguardShowingChanged() {
refreshState();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 9245df0..5366da1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -25,7 +25,6 @@
import android.os.Message;
import android.support.annotation.VisibleForTesting;
import android.util.Pair;
-import android.view.KeyEvent;
import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.IStatusBar;
@@ -92,6 +91,8 @@
private final Object mLock = new Object();
private ArrayList<Callbacks> mCallbacks = new ArrayList<>();
private Handler mHandler = new H(Looper.getMainLooper());
+ private int mDisable1;
+ private int mDisable2;
/**
* These methods are called back on the main thread.
@@ -119,9 +120,9 @@
default void cancelPreloadRecentApps() { }
default void setWindowState(int window, int state) { }
default void showScreenPinningRequest(int taskId) { }
- default void appTransitionPending() { }
+ default void appTransitionPending(boolean forced) { }
default void appTransitionCancelled() { }
- default void appTransitionStarting(long startTime, long duration) { }
+ default void appTransitionStarting(long startTime, long duration, boolean forced) { }
default void appTransitionFinished() { }
default void showAssistDisclosure() { }
default void startAssist(Bundle args) { }
@@ -141,6 +142,7 @@
public void addCallbacks(Callbacks callbacks) {
mCallbacks.add(callbacks);
+ callbacks.disable(mDisable1, mDisable2, false /* animate */);
}
public void removeCallbacks(Callbacks callbacks) {
@@ -164,6 +166,8 @@
public void disable(int state1, int state2) {
synchronized (mLock) {
+ mDisable1 = state1;
+ mDisable2 = state2;
mHandler.removeMessages(MSG_DISABLE);
mHandler.obtainMessage(MSG_DISABLE, state1, state2, null).sendToTarget();
}
@@ -315,9 +319,13 @@
}
public void appTransitionPending() {
+ appTransitionPending(false /* forced */);
+ }
+
+ public void appTransitionPending(boolean forced) {
synchronized (mLock) {
mHandler.removeMessages(MSG_APP_TRANSITION_PENDING);
- mHandler.sendEmptyMessage(MSG_APP_TRANSITION_PENDING);
+ mHandler.obtainMessage(MSG_APP_TRANSITION_PENDING, forced ? 1 : 0, 0).sendToTarget();
}
}
@@ -329,10 +337,14 @@
}
public void appTransitionStarting(long startTime, long duration) {
+ appTransitionStarting(startTime, duration, false /* forced */);
+ }
+
+ public void appTransitionStarting(long startTime, long duration, boolean forced) {
synchronized (mLock) {
mHandler.removeMessages(MSG_APP_TRANSITION_STARTING);
- mHandler.obtainMessage(MSG_APP_TRANSITION_STARTING, Pair.create(startTime, duration))
- .sendToTarget();
+ mHandler.obtainMessage(MSG_APP_TRANSITION_STARTING, forced ? 1 : 0, 0,
+ Pair.create(startTime, duration)).sendToTarget();
}
}
@@ -505,7 +517,7 @@
break;
case MSG_APP_TRANSITION_PENDING:
for (int i = 0; i < mCallbacks.size(); i++) {
- mCallbacks.get(i).appTransitionPending();
+ mCallbacks.get(i).appTransitionPending(msg.arg1 != 0);
}
break;
case MSG_APP_TRANSITION_CANCELLED:
@@ -516,7 +528,8 @@
case MSG_APP_TRANSITION_STARTING:
for (int i = 0; i < mCallbacks.size(); i++) {
Pair<Long, Long> data = (Pair<Long, Long>) msg.obj;
- mCallbacks.get(i).appTransitionStarting(data.first, data.second);
+ mCallbacks.get(i).appTransitionStarting(data.first, data.second,
+ msg.arg1 != 0);
}
break;
case MSG_APP_TRANSITION_FINISHED:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 45eb5df..89041f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -43,6 +43,8 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
@@ -54,10 +56,9 @@
import java.util.List;
// Intimately tied to the design of res/layout/signal_cluster_view.xml
-public class SignalClusterView
- extends LinearLayout
- implements NetworkControllerImpl.SignalCallback,
- SecurityController.SecurityControllerCallback, Tunable {
+public class SignalClusterView extends LinearLayout implements NetworkControllerImpl.SignalCallback,
+ SecurityController.SecurityControllerCallback, Tunable,
+ DarkReceiver {
static final String TAG = "SignalClusterView";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -581,7 +582,8 @@
return colorAccent;
}
- public void setIconTint(int tint, float darkIntensity, Rect tintArea) {
+ @Override
+ public void onDarkChanged(Rect tintArea, float darkIntensity, int tint) {
boolean changed = tint != mIconTint || darkIntensity != mDarkIntensity
|| !mTintArea.equals(tintArea);
mIconTint = tint;
@@ -593,16 +595,16 @@
}
private void applyIconTint() {
- setTint(mVpn, StatusBarIconController.getTint(mTintArea, mVpn, mIconTint));
- setTint(mAirplane, StatusBarIconController.getTint(mTintArea, mAirplane, mIconTint));
+ setTint(mVpn, DarkIconDispatcher.getTint(mTintArea, mVpn, mIconTint));
+ setTint(mAirplane, DarkIconDispatcher.getTint(mTintArea, mAirplane, mIconTint));
applyDarkIntensity(
- StatusBarIconController.getDarkIntensity(mTintArea, mNoSims, mDarkIntensity),
+ DarkIconDispatcher.getDarkIntensity(mTintArea, mNoSims, mDarkIntensity),
mNoSims, mNoSimsDark);
applyDarkIntensity(
- StatusBarIconController.getDarkIntensity(mTintArea, mWifi, mDarkIntensity),
+ DarkIconDispatcher.getDarkIntensity(mTintArea, mWifi, mDarkIntensity),
mWifi, mWifiDark);
applyDarkIntensity(
- StatusBarIconController.getDarkIntensity(mTintArea, mEthernet, mDarkIntensity),
+ DarkIconDispatcher.getDarkIntensity(mTintArea, mEthernet, mDarkIntensity),
mEthernet, mEthernetDark);
for (int i = 0; i < mPhoneStates.size(); i++) {
mPhoneStates.get(i).setIconTint(mIconTint, mDarkIntensity, mTintArea);
@@ -740,10 +742,10 @@
public void setIconTint(int tint, float darkIntensity, Rect tintArea) {
applyDarkIntensity(
- StatusBarIconController.getDarkIntensity(tintArea, mMobile, darkIntensity),
+ DarkIconDispatcher.getDarkIntensity(tintArea, mMobile, darkIntensity),
mMobile, mMobileDark);
- setTint(mMobileType, StatusBarIconController.getTint(tintArea, mMobileType, tint));
- setTint(mMobileRoaming, StatusBarIconController.getTint(tintArea, mMobileRoaming,
+ setTint(mMobileType, DarkIconDispatcher.getTint(tintArea, mMobileType, tint));
+ setTint(mMobileRoaming, DarkIconDispatcher.getTint(tintArea, mMobileRoaming,
tint));
}
}
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 4161389..f53dad5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -32,17 +32,19 @@
import android.view.ViewStub;
import android.view.WindowManager;
import android.widget.LinearLayout;
+
import com.android.systemui.BatteryMeterView;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SwipeHelper;
+import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.NavigationBarView;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.PhoneStatusBarView;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
@@ -75,7 +77,6 @@
createBatteryController();
mCarBatteryController.startListening();
- mConnectedDeviceSignalController.startListening();
}
@Override
@@ -87,32 +88,40 @@
}
@Override
- protected PhoneStatusBarView makeStatusBarView() {
- PhoneStatusBarView statusBarView = super.makeStatusBarView();
+ protected void makeStatusBarView() {
+ super.makeStatusBarView();
- mBatteryMeterView = ((BatteryMeterView) statusBarView.findViewById(R.id.battery));
+ FragmentHostManager manager = FragmentHostManager.get(mStatusBarWindow);
+ manager.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
+ mBatteryMeterView = ((BatteryMeterView) fragment.getView().findViewById(
+ R.id.battery));
- // By default, the BatteryMeterView should not be visible. It will be toggled visible
- // when a device has connected by bluetooth.
- mBatteryMeterView.setVisibility(View.GONE);
+ // By default, the BatteryMeterView should not be visible. It will be toggled
+ // when a device has connected by bluetooth.
+ mBatteryMeterView.setVisibility(View.GONE);
- ViewStub stub = (ViewStub) statusBarView.findViewById(R.id.connected_device_signals_stub);
- View signalsView = stub.inflate();
+ ViewStub stub = (ViewStub) fragment.getView().findViewById(
+ R.id.connected_device_signals_stub);
+ View signalsView = stub.inflate();
- // When a ViewStub if inflated, it does not respect the margins on the inflated view.
- // As a result, manually add the ending margin.
- ((LinearLayout.LayoutParams) signalsView.getLayoutParams()).setMarginEnd(
- mContext.getResources().getDimensionPixelOffset(
- R.dimen.status_bar_connected_device_signal_margin_end));
+ // When a ViewStub if inflated, it does not respect the margins on the
+ // inflated view.
+ // As a result, manually add the ending margin.
+ ((LinearLayout.LayoutParams) signalsView.getLayoutParams()).setMarginEnd(
+ mContext.getResources().getDimensionPixelOffset(
+ R.dimen.status_bar_connected_device_signal_margin_end));
- mConnectedDeviceSignalController = new ConnectedDeviceSignalController(mContext,
- signalsView);
+ if (mConnectedDeviceSignalController != null) {
+ mConnectedDeviceSignalController.stopListening();
+ }
+ mConnectedDeviceSignalController = new ConnectedDeviceSignalController(mContext,
+ signalsView);
+ mConnectedDeviceSignalController.startListening();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "makeStatusBarView(). mBatteryMeterView: " + mBatteryMeterView);
- }
-
- return statusBarView;
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "makeStatusBarView(). mBatteryMeterView: " + mBatteryMeterView);
+ }
+ });
}
private BatteryController createBatteryController() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
new file mode 100644
index 0000000..1f56c56
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -0,0 +1,223 @@
+/*
+ * 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 com.android.systemui.statusbar.phone.StatusBar.reinflateSignalCluster;
+
+import android.annotation.Nullable;
+import android.app.Fragment;
+import android.app.StatusBarManager;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
+import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.SignalClusterView;
+import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.statusbar.policy.EncryptionHelper;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.NetworkController;
+
+/**
+ * Contains the collapsed status bar and handles hiding/showing based on disable flags
+ * and keyguard state. Also manages lifecycle to make sure the views it contains are being
+ * updated by the StatusBarIconController and DarkIconManager while it is attached.
+ */
+public class CollapsedStatusBarFragment extends Fragment implements CommandQueue.Callbacks {
+
+ public static final String TAG = "CollapsedStatusBarFragment";
+ private PhoneStatusBarView mStatusBar;
+ private KeyguardMonitor mKeyguardMonitor;
+ private NetworkController mNetworkController;
+ private LinearLayout mSystemIconArea;
+ private View mNotificationIconAreaInner;
+ private int mDisabled1;
+ private StatusBar mStatusBarComponent;
+ private DarkIconManager mDarkIconManager;
+ private SignalClusterView mSignalClusterView;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ mNetworkController = Dependency.get(NetworkController.class);
+ mStatusBarComponent = SysUiServiceProvider.getComponent(getContext(), StatusBar.class);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.status_bar, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ mStatusBar = (PhoneStatusBarView) view;
+ mDarkIconManager = new DarkIconManager((LinearLayout) view.findViewById(R.id.statusIcons));
+ Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
+ mSystemIconArea = (LinearLayout) mStatusBar.findViewById(R.id.system_icon_area);
+ mSignalClusterView = reinflateSignalCluster(mStatusBar);
+ Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mSignalClusterView);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).removeCallbacks(this);
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mSignalClusterView);
+ Dependency.get(StatusBarIconController.class).removeIconGroup(mDarkIconManager);
+ }
+
+ public void initNotificationIconArea(NotificationIconAreaController
+ notificationIconAreaController) {
+ ViewGroup notificationIconArea = (ViewGroup) mStatusBar
+ .findViewById(R.id.notification_icon_area);
+ mNotificationIconAreaInner =
+ notificationIconAreaController.getNotificationInnerAreaView();
+ if (mNotificationIconAreaInner.getParent() != null) {
+ ((ViewGroup) mNotificationIconAreaInner.getParent())
+ .removeView(mNotificationIconAreaInner);
+ }
+ notificationIconArea.addView(mNotificationIconAreaInner);
+ }
+
+ @Override
+ public void disable(int state1, int state2, boolean animate) {
+ state1 = adjustDisableFlags(state1);
+ final int old1 = mDisabled1;
+ final int diff1 = state1 ^ old1;
+ mDisabled1 = state1;
+ if ((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
+ if ((state1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
+ hideSystemIconArea(animate);
+ } else {
+ showSystemIconArea(animate);
+ }
+ }
+ if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
+ if ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
+ hideNotificationIconArea(animate);
+ } else {
+ showNotificationIconArea(animate);
+ }
+ }
+ }
+
+ protected int adjustDisableFlags(int state) {
+ if (!mStatusBarComponent.isLaunchTransitionFadingAway()
+ && !mKeyguardMonitor.isKeyguardFadingAway()
+ && shouldHideNotificationIcons()) {
+ state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
+ state |= StatusBarManager.DISABLE_SYSTEM_INFO;
+ }
+ if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
+ if (mNetworkController.hasEmergencyCryptKeeperText()) {
+ state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
+ }
+ if (!mNetworkController.isRadioOn()) {
+ state |= StatusBarManager.DISABLE_SYSTEM_INFO;
+ }
+ }
+ return state;
+ }
+
+ private boolean shouldHideNotificationIcons() {
+ return !mStatusBar.isClosed() && mStatusBarComponent.shouldHideNotificationIcons();
+ }
+
+ public void hideSystemIconArea(boolean animate) {
+ animateHide(mSystemIconArea, animate);
+ }
+
+ public void showSystemIconArea(boolean animate) {
+ animateShow(mSystemIconArea, animate);
+ }
+
+ public void hideNotificationIconArea(boolean animate) {
+ animateHide(mNotificationIconAreaInner, animate);
+ }
+
+ public void showNotificationIconArea(boolean animate) {
+ animateShow(mNotificationIconAreaInner, animate);
+ }
+
+ /**
+ * Hides a view.
+ */
+ private void animateHide(final View v, boolean animate) {
+ v.animate().cancel();
+ if (!animate) {
+ v.setAlpha(0f);
+ v.setVisibility(View.INVISIBLE);
+ return;
+ }
+ v.animate()
+ .alpha(0f)
+ .setDuration(160)
+ .setStartDelay(0)
+ .setInterpolator(Interpolators.ALPHA_OUT)
+ .withEndAction(() -> v.setVisibility(View.INVISIBLE));
+ }
+
+ /**
+ * Shows a view, and synchronizes the animation with Keyguard exit animations, if applicable.
+ */
+ private void animateShow(View v, boolean animate) {
+ v.animate().cancel();
+ v.setVisibility(View.VISIBLE);
+ if (!animate) {
+ v.setAlpha(1f);
+ return;
+ }
+ v.animate()
+ .alpha(1f)
+ .setDuration(320)
+ .setInterpolator(Interpolators.ALPHA_IN)
+ .setStartDelay(50)
+
+ // We need to clean up any pending end action from animateHide if we call
+ // both hide and show in the same frame before the animation actually gets started.
+ // cancel() doesn't really remove the end action.
+ .withEndAction(null);
+
+ // Synchronize the motion with the Keyguard fading if necessary.
+ if (mKeyguardMonitor.isKeyguardFadingAway()) {
+ v.animate()
+ .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration())
+ .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
+ .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay())
+ .start();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java
new file mode 100644
index 0000000..020dc25
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.java
@@ -0,0 +1,60 @@
+/*
+ * 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 android.content.Context;
+import android.content.res.Configuration;
+
+import com.android.systemui.ConfigurationChangedReceiver;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+
+import java.util.ArrayList;
+
+public class ConfigurationControllerImpl implements ConfigurationController,
+ ConfigurationChangedReceiver {
+
+ private final ArrayList<ConfigurationListener> mListeners = new ArrayList<>();
+ private int mDensity;
+ private float mFontScale;
+
+ public ConfigurationControllerImpl(Context context) {
+ Configuration currentConfig = context.getResources().getConfiguration();
+ mFontScale = currentConfig.fontScale;
+ mDensity = currentConfig.densityDpi;
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ mListeners.forEach(l -> l.onConfigChanged(newConfig));
+ final float fontScale = newConfig.fontScale;
+ final int density = newConfig.densityDpi;
+ if (density != mDensity || mFontScale != fontScale) {
+ mListeners.forEach(l -> l.onDensityOrFontScaleChanged());
+ mDensity = density;
+ mFontScale = fontScale;
+ }
+ }
+
+ @Override
+ public void addCallback(ConfigurationListener listener) {
+ mListeners.add(listener);
+ listener.onDensityOrFontScaleChanged();
+ }
+
+ @Override
+ public void removeCallback(ConfigurationListener listener) {
+ mListeners.remove(listener);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
new file mode 100644
index 0000000..3f9ae80
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
@@ -0,0 +1,106 @@
+/*
+ * 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 com.android.systemui.statusbar.policy.DarkIconDispatcher.getTint;
+
+import android.animation.ArgbEvaluator;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Rect;
+import android.util.ArrayMap;
+import android.widget.ImageView;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+
+public class DarkIconDispatcherImpl implements DarkIconDispatcher {
+
+ private final LightBarTransitionsController mTransitionsController;
+ private final Rect mTintArea = new Rect();
+ private final ArrayMap<Object, DarkReceiver> mReceivers = new ArrayMap<>();
+
+ private int mIconTint = DEFAULT_ICON_TINT;
+ private float mDarkIntensity;
+ private int mDarkModeIconColorSingleTone;
+ private int mLightModeIconColorSingleTone;
+
+ public DarkIconDispatcherImpl(Context context) {
+ mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
+ mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
+
+ mTransitionsController = new LightBarTransitionsController(context,
+ this::setIconTintInternal);
+ }
+
+ public LightBarTransitionsController getTransitionsController() {
+ return mTransitionsController;
+ }
+
+ public void addDarkReceiver(DarkReceiver receiver) {
+ mReceivers.put(receiver, receiver);
+ receiver.onDarkChanged(mTintArea, mDarkIntensity, mIconTint);
+ }
+
+ public void addDarkReceiver(ImageView imageView) {
+ DarkReceiver receiver = (area, darkIntensity, tint) -> imageView.setImageTintList(
+ ColorStateList.valueOf(getTint(mTintArea, imageView, mIconTint)));
+ mReceivers.put(imageView, receiver);
+ receiver.onDarkChanged(mTintArea, mDarkIntensity, mIconTint);
+ }
+
+ public void removeDarkReceiver(DarkReceiver object) {
+ mReceivers.remove(object);
+ }
+
+ public void removeDarkReceiver(ImageView object) {
+ mReceivers.remove(object);
+ }
+
+ public void applyDark(ImageView object) {
+ mReceivers.get(object).onDarkChanged(mTintArea, mDarkIntensity, mIconTint);
+ }
+
+ /**
+ * Sets the dark area so {@link #setIconsDark} only affects the icons in the specified area.
+ *
+ * @param darkArea the area in which icons should change it's tint, in logical screen
+ * coordinates
+ */
+ public void setIconsDarkArea(Rect darkArea) {
+ if (darkArea == null && mTintArea.isEmpty()) {
+ return;
+ }
+ if (darkArea == null) {
+ mTintArea.setEmpty();
+ } else {
+ mTintArea.set(darkArea);
+ }
+ applyIconTint();
+ }
+
+ private void setIconTintInternal(float darkIntensity) {
+ mDarkIntensity = darkIntensity;
+ mIconTint = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
+ mLightModeIconColorSingleTone, mDarkModeIconColorSingleTone);
+ applyIconTint();
+ }
+
+ private void applyIconTint() {
+ for (int i = 0; i < mReceivers.size(); i++) {
+ mReceivers.valueAt(i).onDarkChanged(mTintArea, mDarkIntensity, mIconTint);
+ }
+ }
+}
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 7c458898..9d699cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -22,6 +22,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -36,7 +37,7 @@
private static final float NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD = 0.1f;
- private final StatusBarIconController mStatusBarIconController;
+ private final DarkIconDispatcher mStatusBarIconController;
private final BatteryController mBatteryController;
private FingerprintUnlockController mFingerprintUnlockController;
@@ -65,8 +66,8 @@
private final Rect mLastFullscreenBounds = new Rect();
private final Rect mLastDockedBounds = new Rect();
- public LightBarController(StatusBarIconController statusBarIconController) {
- mStatusBarIconController = statusBarIconController;
+ public LightBarController() {
+ mStatusBarIconController = Dependency.get(DarkIconDispatcher.class);
mBatteryController = Dependency.get(BatteryController.class);
mBatteryController.addCallback(this);
}
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 07f37ab..6bd959f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -17,13 +17,19 @@
package com.android.systemui.statusbar.phone;
import android.animation.ValueAnimator;
+import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.util.TimeUtils;
import com.android.systemui.Dumpable;
+import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.CommandQueue.Callbacks;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -31,13 +37,14 @@
/**
* Class to control all aspects about light bar changes.
*/
-public class LightBarTransitionsController implements Dumpable {
+public class LightBarTransitionsController implements Dumpable, Callbacks {
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;
+ private final KeyguardMonitor mKeyguardMonitor;
private boolean mTransitionDeferring;
private long mTransitionDeferringStartTime;
@@ -56,9 +63,17 @@
}
};
- public LightBarTransitionsController(DarkIntensityApplier applier) {
+ public LightBarTransitionsController(Context context, DarkIntensityApplier applier) {
mApplier = applier;
mHandler = new Handler();
+ mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
+ SysUiServiceProvider.getComponent(context, CommandQueue.class)
+ .addCallbacks(this);
+ }
+
+ public void destroy(Context context) {
+ SysUiServiceProvider.getComponent(context, CommandQueue.class)
+ .removeCallbacks(this);
}
public void saveState(Bundle outState) {
@@ -71,10 +86,15 @@
setIconTintInternal(savedInstanceState.getFloat(EXTRA_DARK_INTENSITY, 0));
}
- public void appTransitionPending() {
+ @Override
+ public void appTransitionPending(boolean forced) {
+ if (mKeyguardMonitor.isKeyguardGoingAway() && !forced) {
+ return;
+ }
mTransitionPending = true;
}
+ @Override
public void appTransitionCancelled() {
if (mTransitionPending && mTintChangePending) {
mTintChangePending = false;
@@ -83,7 +103,11 @@
mTransitionPending = false;
}
- public void appTransitionStarting(long startTime, long duration) {
+ @Override
+ public void appTransitionStarting(long startTime, long duration, boolean forced) {
+ if (mKeyguardMonitor.isKeyguardGoingAway() && !forced) {
+ return;
+ }
if (mTransitionPending && mTintChangePending) {
mTintChangePending = false;
animateIconTint(mPendingDarkIntensity,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 808cd21..99f8aaf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -118,7 +118,6 @@
private int mSystemUiVisibility;
private LightBarController mLightBarController;
- private boolean mKeyguardGoingAway;
public boolean mHomeBlockedThisTouch;
@@ -195,6 +194,7 @@
@Override
public void onDestroyView() {
super.onDestroyView();
+ mNavigationBarView.getLightTransitionsController().destroy(getContext());
getContext().unregisterReceiver(mBroadcastReceiver);
}
@@ -287,31 +287,6 @@
}
}
- @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 StatusBar can force this when needed.
- */
- public void doAppTransitionStarting(long startTime, long duration) {
- mNavigationBarView.getLightTransitionsController().appTransitionStarting(startTime,
- duration);
- }
-
// Injected from StatusBar at creation.
public void setCurrentSysuiVisibility(int systemUiVisibility) {
mSystemUiVisibility = systemUiVisibility;
@@ -612,10 +587,6 @@
delay + StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
}
- public void setKeyguardGoingAway(boolean keyguardGoingAway) {
- mKeyguardGoingAway = keyguardGoingAway;
- }
-
public BarTransitions getBarTransitions() {
return mNavigationBarView.getBarTransitions();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index 3be5e57..cb925d5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -38,7 +38,8 @@
mView = view;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
- mLightTransitionsController = new LightBarTransitionsController(this::applyDarkIntensity);
+ mLightTransitionsController = new LightBarTransitionsController(view.getContext(),
+ this::applyDarkIntensity);
}
public void init() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 0386398..6d7ab47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -17,6 +17,8 @@
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import java.util.ArrayList;
@@ -26,7 +28,7 @@
* A controller for the space in the status bar to the left of the system icons. This area is
* normally reserved for notifications.
*/
-public class NotificationIconAreaController {
+public class NotificationIconAreaController implements DarkReceiver {
private final NotificationColorUtil mNotificationColorUtil;
private int mIconSize;
@@ -64,11 +66,12 @@
mNotificationIcons = (NotificationIconContainer) mNotificationIconArea.findViewById(
R.id.notificationIcons);
- NotificationShelf shelf = mStatusBar.getNotificationShelf();
+ mNotificationScrollLayout = mStatusBar.getNotificationScrollLayout();
+ }
+
+ public void setupShelf(NotificationShelf shelf) {
mShelfIcons = shelf.getShelfIcons();
shelf.setCollapsedIcons(mNotificationIcons);
-
- mNotificationScrollLayout = mStatusBar.getNotificationScrollLayout();
}
public void onDensityOrFontScaleChanged(Context context) {
@@ -102,23 +105,18 @@
}
/**
- * See {@link StatusBarIconController#setIconsDarkArea}.
+ * See {@link com.android.systemui.statusbar.policy.DarkIconDispatcher#setIconsDarkArea}.
+ * Sets the color that should be used to tint any icons in the notification area.
*
* @param tintArea the area in which to tint the icons, specified in screen coordinates
+ * @param darkIntensity
*/
- public void setTintArea(Rect tintArea) {
+ public void onDarkChanged(Rect tintArea, float darkIntensity, int iconTint) {
if (tintArea == null) {
mTintArea.setEmpty();
} else {
mTintArea.set(tintArea);
}
- applyNotificationIconsTint();
- }
-
- /**
- * Sets the color that should be used to tint any icons in the notification area.
- */
- public void setIconTint(int iconTint) {
mIconTint = iconTint;
applyNotificationIconsTint();
}
@@ -231,7 +229,7 @@
boolean colorize = !isPreL || NotificationUtils.isGrayscale(v, mNotificationColorUtil);
if (colorize) {
v.setImageTintList(ColorStateList.valueOf(
- StatusBarIconController.getTint(mTintArea, v, mIconTint)));
+ DarkIconDispatcher.getTint(mTintArea, v, mIconTint)));
}
v.setIconTint(mIconTint);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index 87a3848..23d3816 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -166,6 +166,10 @@
if (DEBUG) LOG("onPanelPeeked");
}
+ public boolean isClosed() {
+ return mState == STATE_CLOSED;
+ }
+
public void onPanelCollapsed() {
if (DEBUG) LOG("onPanelCollapsed");
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 1044ecf..93f874d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -38,24 +38,35 @@
import com.android.internal.telephony.TelephonyIntents;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.RotationLockTile;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.BluetoothController.Callback;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
import com.android.systemui.statusbar.policy.DataSaverController;
+import com.android.systemui.statusbar.policy.DataSaverController.Listener;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.ZenModeController;
/**
* This class contains all of the policy about which icons are installed in the status
* bar at boot time. It goes through the normal API for icons, even though it probably
* strictly doesn't need to.
*/
-public class PhoneStatusBarPolicy implements Callback, RotationLockController.RotationLockControllerCallback, DataSaverController.Listener {
+public class PhoneStatusBarPolicy implements Callback, Callbacks,
+ RotationLockControllerCallback, Listener,
+ ZenModeController.Callback, DeviceProvisionedListener, KeyguardMonitor.Callback {
private static final String TAG = "PhoneStatusBarPolicy";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -82,7 +93,9 @@
private final StatusBarIconController mIconController;
private final RotationLockController mRotationLockController;
private final DataSaverController mDataSaver;
- private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ private final ZenModeController mZenController;
+ private final DeviceProvisionedController mProvisionedController;
+ private final KeyguardMonitor mKeyguardMonitor;
// Assume it's all good unless we hear otherwise. We don't always seem
// to get broadcasts that it *is* there.
@@ -106,13 +119,15 @@
mCast = Dependency.get(CastController.class);
mHotspot = Dependency.get(HotspotController.class);
mBluetooth = Dependency.get(BluetoothController.class);
- mBluetooth.addCallback(this);
mNextAlarm = Dependency.get(NextAlarmController.class);
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
mUserInfoController = Dependency.get(UserInfoController.class);
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mRotationLockController = Dependency.get(RotationLockController.class);
mDataSaver = Dependency.get(DataSaverController.class);
+ mZenController = Dependency.get(ZenModeController.class);
+ mProvisionedController = Dependency.get(DeviceProvisionedController.class);
+ mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
@@ -127,7 +142,6 @@
mSlotHeadset = context.getString(com.android.internal.R.string.status_bar_headset);
mSlotDataSaver = context.getString(com.android.internal.R.string.status_bar_data_saver);
- mRotationLockController.addCallback(this);
// listen for broadcasts
IntentFilter filter = new IntentFilter();
@@ -158,7 +172,6 @@
// Alarm clock
mIconController.setIcon(mSlotAlarmClock, R.drawable.stat_sys_alarm, null);
mIconController.setIconVisibility(mSlotAlarmClock, false);
- mNextAlarm.addCallback(mNextAlarmCallback);
// zen
mIconController.setIcon(mSlotZen, R.drawable.stat_sys_zen_important, null);
@@ -172,13 +185,11 @@
// cast
mIconController.setIcon(mSlotCast, R.drawable.stat_sys_cast, null);
mIconController.setIconVisibility(mSlotCast, false);
- mCast.addCallback(mCastCallback);
// hotspot
mIconController.setIcon(mSlotHotspot, R.drawable.stat_sys_hotspot,
mContext.getString(R.string.accessibility_status_bar_hotspot));
mIconController.setIconVisibility(mSlotHotspot, mHotspot.isHotspotEnabled());
- mHotspot.addCallback(mHotspotCallback);
// managed profile
mIconController.setIcon(mSlotManagedProfile, R.drawable.stat_sys_managed_profile_status,
@@ -189,15 +200,36 @@
mIconController.setIcon(mSlotDataSaver, R.drawable.stat_sys_data_saver,
context.getString(R.string.accessibility_data_saver_on));
mIconController.setIconVisibility(mSlotDataSaver, false);
+
+ mRotationLockController.addCallback(this);
+ mBluetooth.addCallback(this);
+ mProvisionedController.addCallback(this);
+ mZenController.addCallback(this);
+ mCast.addCallback(mCastCallback);
+ mHotspot.addCallback(mHotspotCallback);
+ mNextAlarm.addCallback(mNextAlarmCallback);
mDataSaver.addCallback(this);
+ mKeyguardMonitor.addCallback(this);
+
+ SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallbacks(this);
}
- public void setStatusBarKeyguardViewManager(
- StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
- mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+ public void destroy() {
+ mRotationLockController.removeCallback(this);
+ mBluetooth.removeCallback(this);
+ mProvisionedController.removeCallback(this);
+ mZenController.removeCallback(this);
+ mCast.removeCallback(mCastCallback);
+ mHotspot.removeCallback(mHotspotCallback);
+ mNextAlarm.removeCallback(mNextAlarmCallback);
+ mDataSaver.removeCallback(this);
+ mKeyguardMonitor.removeCallback(this);
+ SysUiServiceProvider.getComponent(mContext, CommandQueue.class).removeCallbacks(this);
+ mContext.unregisterReceiver(mIntentReceiver);
}
- public void setZenMode(int zen) {
+ @Override
+ public void onZenChanged(int zen) {
mZen = zen;
updateVolumeZen();
}
@@ -394,7 +426,7 @@
if (DEBUG) Log.v(TAG, "updateManagedProfile: mManagedProfileFocused: "
+ mManagedProfileFocused);
final boolean showIcon;
- if (mManagedProfileFocused && !mStatusBarKeyguardViewManager.isShowing()) {
+ if (mManagedProfileFocused && !mKeyguardMonitor.isShowing()) {
showIcon = true;
mIconController.setIcon(mSlotManagedProfile,
R.drawable.stat_sys_managed_profile_status,
@@ -471,15 +503,20 @@
}
};
- public void appTransitionStarting(long startTime, long duration) {
+ @Override
+ public void appTransitionStarting(long startTime, long duration, boolean forced) {
updateManagedProfile();
}
- public void notifyKeyguardShowingChanged() {
+ @Override
+ public void onKeyguardShowingChanged() {
updateManagedProfile();
}
- public void setCurrentUserSetup(boolean userSetup) {
+ @Override
+ public void onUserSetupChanged() {
+ boolean userSetup = mProvisionedController.isUserSetup(
+ mProvisionedController.getCurrentUser());
if (mCurrentUserSetup == userSetup) return;
mCurrentUserSetup = userSetup;
updateAlarm();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 7e088124..b52c26f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -24,9 +24,13 @@
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
+import com.android.systemui.BatteryMeterView;
import com.android.systemui.DejankUtils;
+import com.android.systemui.Dependency;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
public class PhoneStatusBarView extends PanelBar {
private static final String TAG = "PhoneStatusBarView";
@@ -48,6 +52,7 @@
}
}
};
+ private DarkReceiver mBattery;
public PhoneStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -70,6 +75,20 @@
@Override
public void onFinishInflate() {
mBarTransitions.init();
+ mBattery = (DarkReceiver) findViewById(R.id.battery);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ // Always have Battery meters in the status bar observe the dark/light modes.
+ Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mBattery);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(mBattery);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
index 4307a2e..457ed6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStatusBarHeader.java
@@ -178,7 +178,7 @@
SignalClusterView cluster = (SignalClusterView) findViewById(R.id.signal_cluster);
int colorForeground = Utils.getColorAttr(getContext(), android.R.attr.colorForeground);
float intensity = colorForeground == Color.WHITE ? 0 : 1;
- cluster.setIconTint(colorForeground, intensity, new Rect(0, 0, 0, 0));
+ cluster.onDarkChanged(new Rect(0, 0, 0, 0), intensity, colorForeground);
BatteryMeterView battery = (BatteryMeterView) findViewById(R.id.battery);
int colorSecondary = Utils.getColorAttr(getContext(), android.R.attr.textColorSecondary);
battery.setRawColors(colorForeground, colorSecondary);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 942cf0e..433dc3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -173,13 +173,16 @@
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
-import com.android.systemui.statusbar.policy.EncryptionHelper;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
@@ -504,9 +507,6 @@
}
updateQsExpansionEnabled();
}
- if (mIconPolicy != null) {
- mIconPolicy.setCurrentUserSetup(mUserSetup);
- }
}
};
@@ -712,6 +712,8 @@
private BatteryController mBatteryController;
private LogMaker mStatusBarStateLog;
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
+ private NotificationIconAreaController mNotificationIconAreaController;
+ private ConfigurationListener mDensityChangeListener;
private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
final int N = array.size();
@@ -809,8 +811,6 @@
final Configuration currentConfig = mContext.getResources().getConfiguration();
mLocale = currentConfig.locale;
mLayoutDirection = TextUtils.getLayoutDirectionFromLocale(mLocale);
- mFontScale = currentConfig.fontScale;
- mDensity = currentConfig.densityDpi;
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
@@ -847,7 +847,7 @@
int N = iconSlots.size();
int viewIndex = 0;
for (int i=0; i < N; i++) {
- setIcon(iconSlots.get(i), icons.get(i));
+ mCommandQueue.setIcon(iconSlots.get(i), icons.get(i));
}
// Set up the initial notification state.
@@ -914,7 +914,6 @@
// Lastly, call to the icon policy to install/update all the icons.
mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController);
- mIconPolicy.setCurrentUserSetup(mUserSetup);
mSettingsObserver.onChange(false); // set up
mHeadsUpObserver.onChange(true); // set up
@@ -938,18 +937,25 @@
mScreenPinningRequest = new ScreenPinningRequest(mContext);
mFalsingManager = FalsingManager.getInstance(mContext);
+
Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(this);
+
+ mDensityChangeListener = new ConfigurationListener() {
+ @Override
+ public void onDensityOrFontScaleChanged() {
+ StatusBar.this.onDensityOrFontScaleChanged();
+ }
+ };
+ Dependency.get(ConfigurationController.class).addCallback(mDensityChangeListener);
}
protected void createIconController() {
- mIconController = new StatusBarIconController(
- mContext, mStatusBarView, mKeyguardStatusBar, this);
}
// ================================================================================
// Constructing the view
// ================================================================================
- protected PhoneStatusBarView makeStatusBarView() {
+ protected void makeStatusBarView() {
final Context context = mContext;
updateDisplaySize(); // populates mDisplayMetrics
updateResources();
@@ -958,14 +964,37 @@
mStatusBarWindow.setService(this);
mStatusBarWindow.setOnTouchListener(getStatusBarWindowTouchListener());
+ // TODO: Deal with the ugliness that comes from having some of the statusbar broken out
+ // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(
R.id.notification_panel);
+ mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
+ R.id.notification_stack_scroller);
mNotificationPanel.setStatusBar(this);
mNotificationPanel.setGroupManager(mGroupManager);
+ mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
- mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
- mStatusBarView.setBar(this);
- mStatusBarView.setPanel(mNotificationPanel);
+ mNotificationIconAreaController = SystemUIFactory.getInstance()
+ .createNotificationIconAreaController(context, this);
+ inflateShelf();
+ mNotificationIconAreaController.setupShelf(mNotificationShelf);
+ Dependency.get(DarkIconDispatcher.class).addDarkReceiver(mNotificationIconAreaController);
+ FragmentHostManager.get(mStatusBarWindow)
+ .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
+ CollapsedStatusBarFragment statusBarFragment = (CollapsedStatusBarFragment) fragment;
+ statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);
+ mStatusBarView = (PhoneStatusBarView) fragment.getView();
+ mStatusBarView.setBar(this);
+ mStatusBarView.setPanel(mNotificationPanel);
+ mStatusBarView.setScrimController(mScrimController);
+ setAreThereNotifications();
+ }).getFragmentManager()
+ .beginTransaction()
+ .replace(R.id.status_bar_container, new CollapsedStatusBarFragment(), CollapsedStatusBarFragment.TAG)
+ .commit();
+ Dependency.get(StatusBarIconController.class).addIconGroup(
+ new IconManager((ViewGroup) mKeyguardStatusBar.findViewById(R.id.statusIcons)));
+ mIconController = Dependency.get(StatusBarIconController.class);
if (!ActivityManager.isHighEndGfx()) {
mStatusBarWindow.setBackground(null);
@@ -1003,8 +1032,6 @@
// figure out which pixel-format to use for the status bar.
mPixelFormat = PixelFormat.OPAQUE;
- mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
- R.id.notification_stack_scroller);
mStackScroller.setLongPressListener(getNotificationLongClicker());
mStackScroller.setStatusBar(this);
mStackScroller.setGroupManager(mGroupManager);
@@ -1012,7 +1039,6 @@
mGroupManager.setOnGroupChangeListener(mStackScroller);
mVisualStabilityManager.setVisibilityLocationProvider(mStackScroller);
- inflateShelf();
inflateEmptyShadeView();
inflateDismissView();
mExpandedContents = mStackScroller;
@@ -1025,7 +1051,6 @@
mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
}
- mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
mKeyguardStatusView =
(KeyguardStatusView) mStatusBarWindow.findViewById(R.id.keyguard_status_view);
mKeyguardBottomArea =
@@ -1039,8 +1064,6 @@
// set the initial view visibility
setAreThereNotifications();
- createIconController();
-
// TODO: Find better place for this callback.
mBatteryController.addCallback(new BatteryStateChangeCallback() {
@Override
@@ -1057,7 +1080,7 @@
}
});
- mLightBarController = new LightBarController(mIconController);
+ mLightBarController = new LightBarController();
if (mNavigationBar != null) {
mNavigationBar.setLightBarController(mLightBarController);
}
@@ -1081,7 +1104,6 @@
}
mHeadsUpManager.addListener(mScrimController);
mStackScroller.setScrimController(mScrimController);
- mStatusBarView.setScrimController(mScrimController);
mDozeScrimController = new DozeScrimController(mScrimController, context, mStackScroller,
mNotificationPanel);
@@ -1187,8 +1209,6 @@
// Private API call to make the shadows look better for Recents
ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));
-
- return mStatusBarView;
}
protected void createNavigationBar() {
@@ -1262,12 +1282,13 @@
}
// end old BaseStatusBar.onDensityOrFontScaleChanged().
mScrimController.onDensityOrFontScaleChanged();
- mStatusBarView.onDensityOrFontScaleChanged();
+ // TODO: Remove this.
+ if (mStatusBarView != null) mStatusBarView.onDensityOrFontScaleChanged();
if (mBrightnessMirrorController != null) {
mBrightnessMirrorController.onDensityOrFontScaleChanged();
}
inflateSignalClusters();
- mIconController.onDensityOrFontScaleChanged();
+ mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
inflateDismissView();
updateClearAll();
inflateEmptyShadeView();
@@ -1283,12 +1304,11 @@
}
private void inflateSignalClusters() {
- SignalClusterView signalClusterView = reinflateSignalCluster(mStatusBarView);
- mIconController.setSignalCluster(signalClusterView);
reinflateSignalCluster(mKeyguardStatusBar);
}
- private SignalClusterView reinflateSignalCluster(View view) {
+ public static SignalClusterView reinflateSignalCluster(View view) {
+ Context context = view.getContext();
SignalClusterView signalCluster =
(SignalClusterView) view.findViewById(R.id.signal_cluster);
if (signalCluster != null) {
@@ -1297,12 +1317,12 @@
ViewGroup viewParent = (ViewGroup) parent;
int index = viewParent.indexOfChild(signalCluster);
viewParent.removeView(signalCluster);
- SignalClusterView newCluster = (SignalClusterView) LayoutInflater.from(mContext)
+ SignalClusterView newCluster = (SignalClusterView) LayoutInflater.from(context)
.inflate(R.layout.signal_cluster_view, viewParent, false);
ViewGroup.MarginLayoutParams layoutParams =
(ViewGroup.MarginLayoutParams) viewParent.getLayoutParams();
layoutParams.setMarginsRelative(
- mContext.getResources().getDimensionPixelSize(
+ context.getResources().getDimensionPixelSize(
R.dimen.signal_cluster_margin_start),
0, 0, 0);
newCluster.setLayoutParams(layoutParams);
@@ -1426,9 +1446,6 @@
updateNotifications();
}
// end old BaseStatusBar.setZenMode().
- if (mIconPolicy != null) {
- mIconPolicy.setZenMode(mode);
- }
}
protected void startKeyguard() {
@@ -1445,7 +1462,6 @@
mKeyguardIndicationController.setUserInfoController(
Dependency.get(UserInfoController.class));
mFingerprintUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
- mIconPolicy.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mRemoteInputController.addCallback(mStatusBarKeyguardViewManager);
mRemoteInputController.addCallback(new RemoteInputController.Callback() {
@@ -1526,16 +1542,6 @@
}
}
- @Override
- public void setIcon(String slot, StatusBarIcon icon) {
- mIconController.setIcon(slot, icon);
- }
-
- @Override
- public void removeIcon(String slot) {
- mIconController.removeIcon(slot);
- }
-
public UserHandle getCurrentUserHandle() {
return new UserHandle(mCurrentUserId);
}
@@ -1898,7 +1904,7 @@
updateQsExpansionEnabled();
// Let's also update the icons
- mIconController.updateNotificationIcons(mNotificationData);
+ mNotificationIconAreaController.updateNotificationIcons(mNotificationData);
}
/**
@@ -2079,24 +2085,26 @@
hasActiveNotifications() + " clearable=" + clearable);
}
- final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out);
- final boolean showDot = hasActiveNotifications() && !areLightsOn();
- if (showDot != (nlo.getAlpha() == 1.0f)) {
- if (showDot) {
- nlo.setAlpha(0f);
- nlo.setVisibility(View.VISIBLE);
+ if (mStatusBarView != null) {
+ final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out);
+ final boolean showDot = hasActiveNotifications() && !areLightsOn();
+ if (showDot != (nlo.getAlpha() == 1.0f)) {
+ if (showDot) {
+ nlo.setAlpha(0f);
+ nlo.setVisibility(View.VISIBLE);
+ }
+ nlo.animate()
+ .alpha(showDot ? 1 : 0)
+ .setDuration(showDot ? 750 : 250)
+ .setInterpolator(new AccelerateInterpolator(2.0f))
+ .setListener(showDot ? null : new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator _a) {
+ nlo.setVisibility(View.GONE);
+ }
+ })
+ .start();
}
- nlo.animate()
- .alpha(showDot?1:0)
- .setDuration(showDot?750:250)
- .setInterpolator(new AccelerateInterpolator(2.0f))
- .setListener(showDot ? null : new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator _a) {
- nlo.setVisibility(View.GONE);
- }
- })
- .start();
}
findAndUpdateMediaNotifications();
@@ -2420,26 +2428,6 @@
&& mFalsingManager.isReportingEnabled() ? View.VISIBLE : View.INVISIBLE);
}
- protected int adjustDisableFlags(int state) {
- if (!mLaunchTransitionFadingAway && !mKeyguardFadingAway && shouldHideNotificationIcons()) {
- state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
- state |= StatusBarManager.DISABLE_SYSTEM_INFO;
- }
- if (mNetworkController != null && EncryptionHelper.IS_DATA_ENCRYPTED) {
- if (mNetworkController.hasEmergencyCryptKeeperText()) {
- state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
- }
- if (!mNetworkController.isRadioOn()) {
- state |= StatusBarManager.DISABLE_SYSTEM_INFO;
- }
- }
- return state;
- }
-
- private boolean shouldHideNotificationIcons() {
- return mExpandedVisible && mNotificationPanel.shouldHideNotificationIcons();
- }
-
/**
* State is one or more of the DISABLE constants from StatusBarManager.
*/
@@ -2448,7 +2436,6 @@
animate &= mStatusBarWindowState != WINDOW_STATE_HIDDEN;
mDisabledUnmodified1 = state1;
mDisabledUnmodified2 = state2;
- state1 = adjustDisableFlags(state1);
final int old1 = mDisabled1;
final int diff1 = state1 ^ old1;
mDisabled1 = state1;
@@ -2490,28 +2477,13 @@
flagdbg.append(">");
Log.d(TAG, flagdbg.toString());
- if ((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
- if ((state1 & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
- mIconController.hideSystemIconArea(animate);
- } else {
- mIconController.showSystemIconArea(animate);
- }
- }
-
- if ((diff1 & StatusBarManager.DISABLE_CLOCK) != 0) {
- boolean visible = (state1 & StatusBarManager.DISABLE_CLOCK) == 0;
- mIconController.setClockVisibilityByPolicy(visible);
- }
if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) {
if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0) {
animateCollapsePanels();
}
}
- if ((diff1 & (StatusBarManager.DISABLE_HOME
- | StatusBarManager.DISABLE_RECENT
- | StatusBarManager.DISABLE_BACK
- | StatusBarManager.DISABLE_SEARCH)) != 0) {
+ if ((diff1 & StatusBarManager.DISABLE_RECENT) != 0) {
if ((state1 & StatusBarManager.DISABLE_RECENT) != 0) {
// close recents if it's visible
mHandler.removeMessages(MSG_HIDE_RECENT_APPS);
@@ -2519,14 +2491,6 @@
}
}
- if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
- if ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
- mIconController.hideNotificationIconArea(animate);
- } else {
- mIconController.showNotificationIconArea(animate);
- }
- }
-
if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) {
mDisableNotificationAlerts =
(state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
@@ -2740,10 +2704,6 @@
mFalsingManager.onScreenOff();
}
- public NotificationShelf getNotificationShelf() {
- return mNotificationShelf;
- }
-
public NotificationStackScrollLayout getNotificationScrollLayout() {
return mStackScroller;
}
@@ -2757,6 +2717,14 @@
updateNotifications();
}
+ public boolean isLaunchTransitionFadingAway() {
+ return mLaunchTransitionFadingAway;
+ }
+
+ public boolean shouldHideNotificationIcons() {
+ return mNotificationPanel.shouldHideNotificationIcons();
+ }
+
/**
* All changes to the status bar and notifications funnel through here and are batched.
*/
@@ -3162,7 +3130,8 @@
void checkBarModes() {
if (mDemoMode) return;
- checkBarMode(mStatusBarMode, mStatusBarWindowState, getStatusBarTransitions());
+ if (mStatusBarView != null) checkBarMode(mStatusBarMode, mStatusBarWindowState,
+ getStatusBarTransitions());
if (mNavigationBar != null) mNavigationBar.checkNavBarModes();
mNoAnimationOnNextBarModeChange = false;
}
@@ -3183,7 +3152,9 @@
}
private void finishBarAnimations() {
- mStatusBarView.getBarTransitions().finishAnimations();
+ if (mStatusBarView != null) {
+ mStatusBarView.getBarTransitions().finishAnimations();
+ }
if (mNavigationBar != null) {
mNavigationBar.finishBarAnimations();
}
@@ -3363,8 +3334,6 @@
mNotificationData.dump(pw, " ");
}
- mIconController.dump(pw);
-
if (false) {
pw.println("see the logcat for a dump of the views we have created.");
// must happen on ui thread
@@ -3617,15 +3586,6 @@
protected void onConfigurationChanged(Configuration newConfig) {
updateResources();
updateDisplaySize(); // populates mDisplayMetrics
- // Begin old BaseStatusBar.onConfigurationChanged
- final float fontScale = newConfig.fontScale;
- final int density = newConfig.densityDpi;
- if (density != mDensity || mFontScale != fontScale) {
- onDensityOrFontScaleChanged();
- mDensity = density;
- mFontScale = fontScale;
- }
- // End old BaseStatusBar.onConfigurationChanged
if (DEBUG) {
Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
@@ -3946,17 +3906,12 @@
mContext.unregisterReceiver(mDemoReceiver);
mAssistManager.destroy();
- final SignalClusterView signalCluster =
- (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster);
- final SignalClusterView signalClusterKeyguard =
- (SignalClusterView) mKeyguardStatusBar.findViewById(R.id.signal_cluster);
- final SignalClusterView signalClusterQs =
- (SignalClusterView) mHeader.findViewById(R.id.signal_cluster);
if (mQSPanel != null && mQSPanel.getHost() != null) {
mQSPanel.getHost().destroy();
}
Dependency.get(ActivityStarterDelegate.class).setActivityStarterImpl(null);
mDeviceProvisionedController.removeCallback(mUserSetupObserver);
+ Dependency.get(ConfigurationController.class).removeCallback(mDensityChangeListener);
}
private boolean mDemoModeAllowed;
@@ -3989,7 +3944,7 @@
mBatteryController.dispatchDemoCommand(command, args);
}
if (modeChange || command.equals(COMMAND_STATUS)) {
- mIconController.dispatchDemoCommand(command, args);
+ ((StatusBarIconControllerImpl) mIconController).dispatchDemoCommand(command, args);
}
if (mNetworkController != null && (modeChange || command.equals(COMMAND_NETWORK))) {
mNetworkController.dispatchDemoCommand(command, args);
@@ -4132,14 +4087,8 @@
onLaunchTransitionFadingEnded();
}
});
- mIconController.getTransitionsController().appTransitionStarting(
- SystemClock.uptimeMillis(),
- LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
- if (mNavigationBar != null) {
- mNavigationBar.doAppTransitionStarting(
- SystemClock.uptimeMillis(),
- LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
- }
+ mCommandQueue.appTransitionStarting(SystemClock.uptimeMillis(),
+ LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
}
};
if (mNotificationPanel.isLaunchTransitionRunning()) {
@@ -4264,11 +4213,8 @@
// Treat Keyguard exit animation as an app transition to achieve nice transition for status
// bar.
mKeyguardGoingAway = true;
- mIconController.getTransitionsController().appTransitionPending();
- if (mNavigationBar != null) {
- mNavigationBar.setKeyguardGoingAway(true);
- mNavigationBar.appTransitionPending();
- }
+ mKeyguardMonitor.notifyKeyguardGoingAway(true);
+ mCommandQueue.appTransitionPending(true);
}
/**
@@ -4283,16 +4229,14 @@
mKeyguardFadingAwayDelay = delay;
mKeyguardFadingAwayDuration = fadeoutDuration;
mWaitingForKeyguardExit = false;
- mIconController.getTransitionsController().appTransitionStarting(
- startTime + fadeoutDuration
+ mCommandQueue.appTransitionStarting(startTime + fadeoutDuration
- LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
- LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
+ LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
recomputeDisableFlags(fadeoutDuration > 0 /* animate */);
- if (mNavigationBar != null) {
- mNavigationBar.doAppTransitionStarting(
+ mCommandQueue.appTransitionStarting(
startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
- LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION);
- }
+ LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
+ mKeyguardMonitor.notifyKeyguardFadingAway(delay, fadeoutDuration);
}
public boolean isKeyguardFadingAway() {
@@ -4305,9 +4249,7 @@
public void finishKeyguardFadingAway() {
mKeyguardFadingAway = false;
mKeyguardGoingAway = false;
- if (mNavigationBar != null) {
- mNavigationBar.setKeyguardGoingAway(false);
- }
+ mKeyguardMonitor.notifyKeyguardDoneFading();
}
public void stopWaitingForKeyguardExit() {
@@ -4357,7 +4299,6 @@
} else {
mScrimController.setKeyguardShowing(false);
}
- mIconPolicy.notifyKeyguardShowingChanged();
mNotificationPanel.setBarState(mState, mKeyguardFadingAway, goingToFullShade);
updateDozingState();
updatePublicMode();
@@ -4945,33 +4886,11 @@
}
@Override
- public void appTransitionPending() {
- // Use own timings when Keyguard is going away, see keyguardGoingAway and
- // setKeyguardFadingAway
- if (!mKeyguardFadingAway) {
- mIconController.getTransitionsController().appTransitionPending();
- }
- }
-
- @Override
public void appTransitionCancelled() {
- mIconController.getTransitionsController().appTransitionCancelled();
EventBus.getDefault().send(new AppTransitionFinishedEvent());
}
@Override
- public void appTransitionStarting(long startTime, long duration) {
- // Use own timings when Keyguard is going away, see keyguardGoingAway and
- // setKeyguardFadingAway.
- if (!mKeyguardGoingAway) {
- mIconController.getTransitionsController().appTransitionStarting(startTime, duration);
- }
- if (mIconPolicy != null) {
- mIconPolicy.appTransitionStarting(startTime, duration);
- }
- }
-
- @Override
public void appTransitionFinished() {
EventBus.getDefault().send(new AppTransitionFinishedEvent());
}
@@ -5180,7 +5099,6 @@
private boolean mVisibleToUser;
private Locale mLocale;
- private float mFontScale;
protected boolean mUseHeadsUp = false;
protected boolean mHeadsUpTicker = false;
@@ -5197,7 +5115,6 @@
private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
private UserManager mUserManager;
- private int mDensity;
protected KeyguardManager mKeyguardManager;
private LockPatternUtils mLockPatternUtils;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 41f8a91..c339da7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -1,502 +1,48 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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
+ * 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
+ * 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 android.animation.ArgbEvaluator;
import android.content.Context;
-import android.content.res.ColorStateList;
-import android.content.res.Resources;
-import android.graphics.Color;
-import android.graphics.Rect;
-import android.graphics.drawable.Icon;
-import android.os.Bundle;
-import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArraySet;
-import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.TextView;
+
import com.android.internal.statusbar.StatusBarIcon;
-import com.android.systemui.BatteryMeterView;
import com.android.systemui.Dependency;
-import com.android.systemui.FontSizeUtils;
-import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.SystemUIFactory;
-import com.android.systemui.statusbar.NotificationData;
-import com.android.systemui.statusbar.NotificationShelf;
-import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.StatusBarIconView;
-import com.android.systemui.tuner.TunerService;
-import com.android.systemui.tuner.TunerService.Tunable;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
-import java.io.PrintWriter;
-import java.util.ArrayList;
+public interface StatusBarIconController {
-/**
- * Controls everything regarding the icons in the status bar and on Keyguard, including, but not
- * limited to: notification icons, signal cluster, additional status icons, and clock in the status
- * bar.
- */
-public class StatusBarIconController extends StatusBarIconList implements Tunable {
+ public void addIconGroup(IconManager iconManager);
+ public void removeIconGroup(IconManager iconManager);
+ public void setExternalIcon(String slot);
+ public void setIcon(String slot, int resourceId, CharSequence contentDescription);
+ public void setIcon(String slot, StatusBarIcon icon);
+ public void setIconVisibility(String slotTty, boolean b);
+ public void removeIcon(String slot);
public static final String ICON_BLACKLIST = "icon_blacklist";
- public static final int DEFAULT_ICON_TINT = Color.WHITE;
-
- private Context mContext;
- private StatusBar mStatusBar;
- private DemoStatusIcons mDemoStatusIcons;
-
- private LinearLayout mSystemIconArea;
- private LinearLayout mStatusIcons;
- private SignalClusterView mSignalCluster;
- private LinearLayout mStatusIconsKeyguard;
-
- private NotificationIconAreaController mNotificationIconAreaController;
- private View mNotificationIconAreaInner;
- private NotificationShelf mNotificationShelf;
-
- private BatteryMeterView mBatteryMeterView;
- private BatteryMeterView mBatteryMeterViewKeyguard;
- private TextView mClock;
-
- private int mIconSize;
- private int mIconHPadding;
-
- private int mIconTint = DEFAULT_ICON_TINT;
- private float mDarkIntensity;
- private final Rect mTintArea = new Rect();
- private static final Rect sTmpRect = new Rect();
- private static final int[] sTmpInt2 = new int[2];
-
- private int mDarkModeIconColorSingleTone;
- private int mLightModeIconColorSingleTone;
-
- private final LightBarTransitionsController mTransitionsController;
-
- private boolean mClockVisibleByPolicy = true;
- private boolean mClockVisibleByUser = true;
-
- private final ArraySet<String> mIconBlacklist = new ArraySet<>();
-
- public StatusBarIconController(Context context, View statusBar, View keyguardStatusBar,
- StatusBar phoneStatusBar) {
- super(context.getResources().getStringArray(
- com.android.internal.R.array.config_statusBarIcons));
- mContext = context;
- mStatusBar = phoneStatusBar;
- mSystemIconArea = (LinearLayout) statusBar.findViewById(R.id.system_icon_area);
- mStatusIcons = (LinearLayout) statusBar.findViewById(R.id.statusIcons);
- mSignalCluster = (SignalClusterView) statusBar.findViewById(R.id.signal_cluster);
-
- mNotificationShelf = phoneStatusBar.getNotificationShelf();
- mNotificationIconAreaController = SystemUIFactory.getInstance()
- .createNotificationIconAreaController(context, phoneStatusBar);
- mNotificationIconAreaInner =
- mNotificationIconAreaController.getNotificationInnerAreaView();
-
- ViewGroup notificationIconArea =
- (ViewGroup) statusBar.findViewById(R.id.notification_icon_area);
- notificationIconArea.addView(mNotificationIconAreaInner);
-
- mStatusIconsKeyguard = (LinearLayout) keyguardStatusBar.findViewById(R.id.statusIcons);
-
- mBatteryMeterView = (BatteryMeterView) statusBar.findViewById(R.id.battery);
- mBatteryMeterViewKeyguard = (BatteryMeterView) keyguardStatusBar.findViewById(R.id.battery);
- scaleBatteryMeterViews(context);
-
- mClock = (TextView) statusBar.findViewById(R.id.clock);
- mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
- mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
- loadDimens();
-
- Dependency.get(TunerService.class).addTunable(this, ICON_BLACKLIST);
-
- mTransitionsController = new LightBarTransitionsController(this::setIconTintInternal);
- }
-
- public void setSignalCluster(SignalClusterView signalCluster) {
- mSignalCluster = signalCluster;
- }
-
- public LightBarTransitionsController getTransitionsController() {
- return mTransitionsController;
- }
-
- /**
- * Looks up the scale factor for status bar icons and scales the battery view by that amount.
- */
- private void scaleBatteryMeterViews(Context context) {
- Resources res = context.getResources();
- TypedValue typedValue = new TypedValue();
-
- res.getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true);
- float iconScaleFactor = typedValue.getFloat();
-
- int batteryHeight = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_height);
- int batteryWidth = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_width);
- int marginBottom = res.getDimensionPixelSize(R.dimen.battery_margin_bottom);
-
- LinearLayout.LayoutParams scaledLayoutParams = new LinearLayout.LayoutParams(
- (int) (batteryWidth * iconScaleFactor), (int) (batteryHeight * iconScaleFactor));
- scaledLayoutParams.setMarginsRelative(0, 0, 0, marginBottom);
-
- mBatteryMeterView.setLayoutParams(scaledLayoutParams);
- mBatteryMeterViewKeyguard.setLayoutParams(scaledLayoutParams);
- }
-
- @Override
- public void onTuningChanged(String key, String newValue) {
- if (!ICON_BLACKLIST.equals(key)) {
- return;
- }
- mIconBlacklist.clear();
- mIconBlacklist.addAll(getIconBlacklist(newValue));
- ArrayList<StatusBarIconView> views = new ArrayList<StatusBarIconView>();
- // Get all the current views.
- for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
- views.add((StatusBarIconView) mStatusIcons.getChildAt(i));
- }
- // Remove all the icons.
- for (int i = views.size() - 1; i >= 0; i--) {
- removeIcon(views.get(i).getSlot());
- }
- // Add them all back
- for (int i = 0; i < views.size(); i++) {
- setIcon(views.get(i).getSlot(), views.get(i).getStatusBarIcon());
- }
-
- setClockVisibleByUser(!StatusBarIconController.getIconBlacklist(newValue)
- .contains("clock"));
- updateClockVisibility();
- }
- private void loadDimens() {
- mIconSize = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_icon_size);
- mIconHPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.status_bar_icon_padding);
- }
-
- private void addSystemIcon(int index, StatusBarIcon icon) {
- String slot = getSlot(index);
- int viewIndex = getViewIndex(index);
- boolean blocked = mIconBlacklist.contains(slot);
- StatusBarIconView view = new StatusBarIconView(mContext, slot, null, blocked);
- view.set(icon);
-
- LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
- lp.setMargins(mIconHPadding, 0, mIconHPadding, 0);
- mStatusIcons.addView(view, viewIndex, lp);
-
- view = new StatusBarIconView(mContext, slot, null, blocked);
- view.set(icon);
- mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize));
- applyIconTint();
- }
-
- public void setIcon(String slot, int resourceId, CharSequence contentDescription) {
- int index = getSlotIndex(slot);
- StatusBarIcon icon = getIcon(index);
- if (icon == null) {
- icon = new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
- Icon.createWithResource(mContext, resourceId), 0, 0, contentDescription);
- setIcon(slot, icon);
- } else {
- icon.icon = Icon.createWithResource(mContext, resourceId);
- icon.contentDescription = contentDescription;
- handleSet(index, icon);
- }
- }
-
- public void setExternalIcon(String slot) {
- int viewIndex = getViewIndex(getSlotIndex(slot));
- int height = mContext.getResources().getDimensionPixelSize(
- R.dimen.status_bar_icon_drawing_size);
- ImageView imageView = (ImageView) mStatusIcons.getChildAt(viewIndex);
- imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
- imageView.setAdjustViewBounds(true);
- setHeightAndCenter(imageView, height);
- imageView = (ImageView) mStatusIconsKeyguard.getChildAt(viewIndex);
- imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
- imageView.setAdjustViewBounds(true);
- setHeightAndCenter(imageView, height);
- }
-
- private void setHeightAndCenter(ImageView imageView, int height) {
- ViewGroup.LayoutParams params = imageView.getLayoutParams();
- params.height = height;
- if (params instanceof LinearLayout.LayoutParams) {
- ((LinearLayout.LayoutParams) params).gravity = Gravity.CENTER_VERTICAL;
- }
- imageView.setLayoutParams(params);
- }
-
- public void setIcon(String slot, StatusBarIcon icon) {
- setIcon(getSlotIndex(slot), icon);
- }
-
- public void removeIcon(String slot) {
- int index = getSlotIndex(slot);
- removeIcon(index);
- }
-
- public void setIconVisibility(String slot, boolean visibility) {
- int index = getSlotIndex(slot);
- StatusBarIcon icon = getIcon(index);
- if (icon == null || icon.visible == visibility) {
- return;
- }
- icon.visible = visibility;
- handleSet(index, icon);
- }
-
- @Override
- public void removeIcon(int index) {
- if (getIcon(index) == null) {
- return;
- }
- super.removeIcon(index);
- int viewIndex = getViewIndex(index);
- mStatusIcons.removeViewAt(viewIndex);
- mStatusIconsKeyguard.removeViewAt(viewIndex);
- }
-
- @Override
- public void setIcon(int index, StatusBarIcon icon) {
- if (icon == null) {
- removeIcon(index);
- return;
- }
- boolean isNew = getIcon(index) == null;
- super.setIcon(index, icon);
- if (isNew) {
- addSystemIcon(index, icon);
- } else {
- handleSet(index, icon);
- }
- }
-
- private void handleSet(int index, StatusBarIcon icon) {
- int viewIndex = getViewIndex(index);
- StatusBarIconView view = (StatusBarIconView) mStatusIcons.getChildAt(viewIndex);
- view.set(icon);
- view = (StatusBarIconView) mStatusIconsKeyguard.getChildAt(viewIndex);
- view.set(icon);
- applyIconTint();
- }
-
- public void updateNotificationIcons(NotificationData notificationData) {
- mNotificationIconAreaController.updateNotificationIcons(notificationData);
- }
-
- public void hideSystemIconArea(boolean animate) {
- animateHide(mSystemIconArea, animate);
- }
-
- public void showSystemIconArea(boolean animate) {
- animateShow(mSystemIconArea, animate);
- }
-
- public void hideNotificationIconArea(boolean animate) {
- animateHide(mNotificationIconAreaInner, animate);
- }
-
- public void showNotificationIconArea(boolean animate) {
- animateShow(mNotificationIconAreaInner, animate);
- }
-
- public void setClockVisibleByUser(boolean visible) {
- mClockVisibleByUser = visible;
- updateClockVisibility();
- }
-
- public void setClockVisibilityByPolicy(boolean visible) {
- mClockVisibleByPolicy = visible;
- updateClockVisibility();
- }
-
- private void updateClockVisibility() {
- int visibility = (mClockVisibleByPolicy && mClockVisibleByUser)
- ? View.VISIBLE : View.GONE;
- mClock.setVisibility(visibility);
- }
-
- public void dump(PrintWriter pw) {
- int N = mStatusIcons.getChildCount();
- pw.println(" icon views: " + N);
- for (int i=0; i<N; i++) {
- StatusBarIconView ic = (StatusBarIconView) mStatusIcons.getChildAt(i);
- pw.println(" [" + i + "] icon=" + ic);
- }
- super.dump(pw);
- }
-
- public void dispatchDemoCommand(String command, Bundle args) {
- if (mDemoStatusIcons == null) {
- mDemoStatusIcons = new DemoStatusIcons(mStatusIcons, mIconSize);
- }
- mDemoStatusIcons.dispatchDemoCommand(command, args);
- }
-
- /**
- * Hides a view.
- */
- private void animateHide(final View v, boolean animate) {
- v.animate().cancel();
- if (!animate) {
- v.setAlpha(0f);
- v.setVisibility(View.INVISIBLE);
- return;
- }
- v.animate()
- .alpha(0f)
- .setDuration(160)
- .setStartDelay(0)
- .setInterpolator(Interpolators.ALPHA_OUT)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- v.setVisibility(View.INVISIBLE);
- }
- });
- }
-
- /**
- * Shows a view, and synchronizes the animation with Keyguard exit animations, if applicable.
- */
- private void animateShow(View v, boolean animate) {
- v.animate().cancel();
- v.setVisibility(View.VISIBLE);
- if (!animate) {
- v.setAlpha(1f);
- return;
- }
- v.animate()
- .alpha(1f)
- .setDuration(320)
- .setInterpolator(Interpolators.ALPHA_IN)
- .setStartDelay(50)
-
- // We need to clean up any pending end action from animateHide if we call
- // both hide and show in the same frame before the animation actually gets started.
- // cancel() doesn't really remove the end action.
- .withEndAction(null);
-
- // Synchronize the motion with the Keyguard fading if necessary.
- if (mStatusBar.isKeyguardFadingAway()) {
- v.animate()
- .setDuration(mStatusBar.getKeyguardFadingAwayDuration())
- .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
- .setStartDelay(mStatusBar.getKeyguardFadingAwayDelay())
- .start();
- }
- }
-
- /**
- * Sets the dark area so {@link #setIconsDark} only affects the icons in the specified area.
- *
- * @param darkArea the area in which icons should change it's tint, in logical screen
- * coordinates
- */
- public void setIconsDarkArea(Rect darkArea) {
- if (darkArea == null && mTintArea.isEmpty()) {
- return;
- }
- if (darkArea == null) {
- mTintArea.setEmpty();
- } else {
- mTintArea.set(darkArea);
- }
- applyIconTint();
- mNotificationIconAreaController.setTintArea(darkArea);
- }
-
- private void setIconTintInternal(float darkIntensity) {
- mDarkIntensity = darkIntensity;
- mIconTint = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
- mLightModeIconColorSingleTone, mDarkModeIconColorSingleTone);
- mNotificationIconAreaController.setIconTint(mIconTint);
- applyIconTint();
- }
-
- /**
- * @return the tint to apply to {@param view} depending on the desired tint {@param color} and
- * the screen {@param tintArea} in which to apply that tint
- */
- public static int getTint(Rect tintArea, View view, int color) {
- if (isInArea(tintArea, view)) {
- return color;
- } else {
- return DEFAULT_ICON_TINT;
- }
- }
-
- /**
- * @return the dark intensity to apply to {@param view} depending on the desired dark
- * {@param intensity} and the screen {@param tintArea} in which to apply that intensity
- */
- public static float getDarkIntensity(Rect tintArea, View view, float intensity) {
- if (isInArea(tintArea, view)) {
- return intensity;
- } else {
- return 0f;
- }
- }
-
- /**
- * @return true if more than half of the {@param view} area are in {@param area}, false
- * otherwise
- */
- private static boolean isInArea(Rect area, View view) {
- if (area.isEmpty()) {
- return true;
- }
- sTmpRect.set(area);
- view.getLocationOnScreen(sTmpInt2);
- int left = sTmpInt2[0];
-
- int intersectStart = Math.max(left, area.left);
- int intersectEnd = Math.min(left + view.getWidth(), area.right);
- int intersectAmount = Math.max(0, intersectEnd - intersectStart);
-
- boolean coversFullStatusBar = area.top <= 0;
- boolean majorityOfWidth = 2 * intersectAmount > view.getWidth();
- return majorityOfWidth && coversFullStatusBar;
- }
-
- private void applyIconTint() {
- for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
- StatusBarIconView v = (StatusBarIconView) mStatusIcons.getChildAt(i);
- v.setImageTintList(ColorStateList.valueOf(getTint(mTintArea, v, mIconTint)));
- }
- mSignalCluster.setIconTint(mIconTint, mDarkIntensity, mTintArea);
- mBatteryMeterView.setDarkIntensity(
- isInArea(mTintArea, mBatteryMeterView) ? mDarkIntensity : 0);
- mClock.setTextColor(getTint(mTintArea, mClock, mIconTint));
- }
public static ArraySet<String> getIconBlacklist(String blackListStr) {
- ArraySet<String> ret = new ArraySet<String>();
+ ArraySet<String> ret = new ArraySet<>();
if (blackListStr == null) {
blackListStr = "rotate,headset";
}
@@ -509,34 +55,110 @@
return ret;
}
- public void onDensityOrFontScaleChanged() {
- loadDimens();
- mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
- updateClock();
- for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
- View child = mStatusIcons.getChildAt(i);
+
+ /**
+ * Version of ViewGroup that observers state from the DarkIconDispatcher.
+ */
+ public static class DarkIconManager extends IconManager {
+ private final DarkIconDispatcher mDarkIconDispatcher;
+ private int mIconHPadding;
+
+ public DarkIconManager(LinearLayout linearLayout) {
+ super(linearLayout);
+ mIconHPadding = mContext.getResources().getDimensionPixelSize(
+ R.dimen.status_bar_icon_padding);
+ mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
+ }
+
+ @Override
+ protected void onIconAdded(int index, String slot, boolean blocked, StatusBarIcon icon) {
+ StatusBarIconView view = new StatusBarIconView(mContext, slot, null, blocked);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
lp.setMargins(mIconHPadding, 0, mIconHPadding, 0);
- child.setLayoutParams(lp);
+ mGroup.addView(view, index, lp);
+ mDarkIconDispatcher.addDarkReceiver(view);
}
- for (int i = 0; i < mStatusIconsKeyguard.getChildCount(); i++) {
- View child = mStatusIconsKeyguard.getChildAt(i);
- LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
- child.setLayoutParams(lp);
+
+ @Override
+ protected void destroy() {
+ for (int i = 0; i < mGroup.getChildCount(); i++) {
+ mDarkIconDispatcher.removeDarkReceiver((ImageView) mGroup.getChildAt(i));
+ }
+ mGroup.removeAllViews();
}
- scaleBatteryMeterViews(mContext);
+
+ @Override
+ protected void onRemoveIcon(int viewIndex) {
+ mDarkIconDispatcher.removeDarkReceiver((ImageView) mGroup.getChildAt(viewIndex));
+ super.onRemoveIcon(viewIndex);
+ }
+
+ @Override
+ public void onSetIcon(int viewIndex, StatusBarIcon icon) {
+ super.onSetIcon(viewIndex, icon);
+ mDarkIconDispatcher.applyDark((ImageView) mGroup.getChildAt(viewIndex));
+ }
}
- private void updateClock() {
- FontSizeUtils.updateFontSize(mClock, R.dimen.status_bar_clock_size);
- mClock.setPaddingRelative(
- mContext.getResources().getDimensionPixelSize(
- R.dimen.status_bar_clock_starting_padding),
- 0,
- mContext.getResources().getDimensionPixelSize(
- R.dimen.status_bar_clock_end_padding),
- 0);
+ /**
+ * Turns info from StatusBarIconController into ImageViews in a ViewGroup.
+ */
+ public static class IconManager {
+ protected final ViewGroup mGroup;
+ protected final Context mContext;
+ protected final int mIconSize;
+
+ public IconManager(ViewGroup group) {
+ mGroup = group;
+ mContext = group.getContext();
+ mIconSize = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_icon_size);
+ }
+
+ protected void onIconAdded(int index, String slot, boolean blocked, StatusBarIcon icon) {
+ StatusBarIconView view = new StatusBarIconView(mContext, slot, null, blocked);
+ view.set(icon);
+ mGroup.addView(view, index, new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize));
+ }
+
+ protected void destroy() {
+ mGroup.removeAllViews();
+ }
+
+ protected void onIconExternal(int viewIndex, int height) {
+ ImageView imageView = (ImageView) mGroup.getChildAt(viewIndex);
+ imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
+ imageView.setAdjustViewBounds(true);
+ setHeightAndCenter(imageView, height);
+ }
+
+ protected void onDensityOrFontScaleChanged() {
+ for (int i = 0; i < mGroup.getChildCount(); i++) {
+ View child = mGroup.getChildAt(i);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
+ child.setLayoutParams(lp);
+ }
+ }
+
+ private void setHeightAndCenter(ImageView imageView, int height) {
+ ViewGroup.LayoutParams params = imageView.getLayoutParams();
+ params.height = height;
+ if (params instanceof LinearLayout.LayoutParams) {
+ ((LinearLayout.LayoutParams) params).gravity = Gravity.CENTER_VERTICAL;
+ }
+ imageView.setLayoutParams(params);
+ }
+
+ protected void onRemoveIcon(int viewIndex) {
+ mGroup.removeViewAt(viewIndex);
+ }
+
+ public void onSetIcon(int viewIndex, StatusBarIcon icon) {
+ StatusBarIconView view = (StatusBarIconView) mGroup.getChildAt(viewIndex);
+ view.set(icon);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
new file mode 100644
index 0000000..70b92ad
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -0,0 +1,230 @@
+/*
+ * 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 android.content.Context;
+import android.graphics.drawable.Icon;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
+import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Receives the callbacks from CommandQueue related to icons and tracks the state of
+ * all the icons. Dispatches this state to any IconManagers that are currently
+ * registered with it.
+ */
+public class StatusBarIconControllerImpl extends StatusBarIconList implements Tunable,
+ ConfigurationListener, Dumpable, CommandQueue.Callbacks, StatusBarIconController {
+
+ private final DarkIconDispatcher mDarkIconDispatcher;
+
+ private Context mContext;
+ private DemoStatusIcons mDemoStatusIcons;
+
+ private final ArrayList<IconManager> mIconGroups = new ArrayList<>();
+
+ private final ArraySet<String> mIconBlacklist = new ArraySet<>();
+
+ public StatusBarIconControllerImpl(Context context) {
+ super(context.getResources().getStringArray(
+ com.android.internal.R.array.config_statusBarIcons));
+ Dependency.get(ConfigurationController.class).addCallback(this);
+ mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
+ mContext = context;
+
+ loadDimens();
+
+ SysUiServiceProvider.getComponent(context, CommandQueue.class)
+ .addCallbacks(this);
+ Dependency.get(TunerService.class).addTunable(this, ICON_BLACKLIST);
+ }
+
+ @Override
+ public void addIconGroup(IconManager group) {
+ mIconGroups.add(group);
+ for (int i = 0; i < mIcons.size(); i++) {
+ StatusBarIcon icon = mIcons.get(i);
+ if (icon != null) {
+ String slot = mSlots.get(i);
+ boolean blocked = mIconBlacklist.contains(slot);
+ group.onIconAdded(getViewIndex(getSlotIndex(slot)), slot, blocked, icon);
+ }
+ }
+ }
+
+ @Override
+ public void removeIconGroup(IconManager group) {
+ group.destroy();
+ mIconGroups.remove(group);
+ }
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (!ICON_BLACKLIST.equals(key)) {
+ return;
+ }
+ mIconBlacklist.clear();
+ mIconBlacklist.addAll(StatusBarIconController.getIconBlacklist(newValue));
+ ArrayList<StatusBarIcon> current = new ArrayList<>(mIcons);
+ ArrayList<String> currentSlots = new ArrayList<>(mSlots);
+ // Remove all the icons.
+ for (int i = current.size() - 1; i >= 0; i--) {
+ removeIcon(currentSlots.get(i));
+ }
+ // Add them all back
+ for (int i = 0; i < current.size(); i++) {
+ setIcon(currentSlots.get(i), current.get(i));
+ }
+ }
+
+ private void loadDimens() {
+ }
+
+ private void addSystemIcon(int index, StatusBarIcon icon) {
+ String slot = getSlot(index);
+ int viewIndex = getViewIndex(index);
+ boolean blocked = mIconBlacklist.contains(slot);
+
+ mIconGroups.forEach(l -> l.onIconAdded(viewIndex, slot, blocked, icon));
+ }
+
+ @Override
+ public void setIcon(String slot, int resourceId, CharSequence contentDescription) {
+ int index = getSlotIndex(slot);
+ StatusBarIcon icon = getIcon(index);
+ if (icon == null) {
+ icon = new StatusBarIcon(UserHandle.SYSTEM, mContext.getPackageName(),
+ Icon.createWithResource(mContext, resourceId), 0, 0, contentDescription);
+ setIcon(slot, icon);
+ } else {
+ icon.icon = Icon.createWithResource(mContext, resourceId);
+ icon.contentDescription = contentDescription;
+ handleSet(index, icon);
+ }
+ }
+
+ @Override
+ public void setExternalIcon(String slot) {
+ int viewIndex = getViewIndex(getSlotIndex(slot));
+ int height = mContext.getResources().getDimensionPixelSize(
+ R.dimen.status_bar_icon_drawing_size);
+ mIconGroups.forEach(l -> l.onIconExternal(viewIndex, height));
+ }
+
+ @Override
+ public void setIcon(String slot, StatusBarIcon icon) {
+ setIcon(getSlotIndex(slot), icon);
+ }
+
+ @Override
+ public void removeIcon(String slot) {
+ int index = getSlotIndex(slot);
+ removeIcon(index);
+ }
+
+ public void setIconVisibility(String slot, boolean visibility) {
+ int index = getSlotIndex(slot);
+ StatusBarIcon icon = getIcon(index);
+ if (icon == null || icon.visible == visibility) {
+ return;
+ }
+ icon.visible = visibility;
+ handleSet(index, icon);
+ }
+
+ @Override
+ public void removeIcon(int index) {
+ if (getIcon(index) == null) {
+ return;
+ }
+ super.removeIcon(index);
+ int viewIndex = getViewIndex(index);
+ mIconGroups.forEach(l -> l.onRemoveIcon(viewIndex));
+ }
+
+ @Override
+ public void setIcon(int index, StatusBarIcon icon) {
+ if (icon == null) {
+ removeIcon(index);
+ return;
+ }
+ boolean isNew = getIcon(index) == null;
+ super.setIcon(index, icon);
+ if (isNew) {
+ addSystemIcon(index, icon);
+ } else {
+ handleSet(index, icon);
+ }
+ }
+
+ private void handleSet(int index, StatusBarIcon icon) {
+ int viewIndex = getViewIndex(index);
+ mIconGroups.forEach(l -> l.onSetIcon(viewIndex, icon));
+ }
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ // TODO: Dump info about all icon groups?
+ ViewGroup statusIcons = mIconGroups.get(0).mGroup;
+ int N = statusIcons.getChildCount();
+ pw.println(" icon views: " + N);
+ for (int i = 0; i < N; i++) {
+ StatusBarIconView ic = (StatusBarIconView) statusIcons.getChildAt(i);
+ pw.println(" [" + i + "] icon=" + ic);
+ }
+ super.dump(pw);
+ }
+
+ public void dispatchDemoCommand(String command, Bundle args) {
+ if (mDemoStatusIcons == null) {
+ // TODO: Rework how we handle demo mode.
+ int iconSize = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_icon_size);
+ mDemoStatusIcons = new DemoStatusIcons((LinearLayout) mIconGroups.get(0).mGroup,
+ iconSize);
+ }
+ mDemoStatusIcons.dispatchDemoCommand(command, args);
+ }
+
+ @Override
+ public void onDensityOrFontScaleChanged() {
+ loadDimens();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
index 660672d..f600908 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
@@ -22,8 +22,8 @@
import java.util.ArrayList;
public class StatusBarIconList {
- private ArrayList<String> mSlots = new ArrayList<>();
- private ArrayList<StatusBarIcon> mIcons = new ArrayList<>();
+ protected ArrayList<String> mSlots = new ArrayList<>();
+ protected ArrayList<StatusBarIcon> mIcons = new ArrayList<>();
public StatusBarIconList(String[] slots) {
final int N = slots.length;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index ffc0d97..bb0748c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -19,11 +19,14 @@
import libcore.icu.LocaleData;
import android.app.ActivityManager;
+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.content.res.TypedArray;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
@@ -35,12 +38,18 @@
import android.text.style.RelativeSizeSpan;
import android.util.AttributeSet;
import android.view.Display;
+import android.view.View;
import android.widget.TextView;
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
+import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -52,10 +61,14 @@
/**
* Digital clock for the status bar.
*/
-public class Clock extends TextView implements DemoMode, Tunable {
+public class Clock extends TextView implements DemoMode, Tunable, CommandQueue.Callbacks,
+ DarkReceiver, ConfigurationListener {
public static final String CLOCK_SECONDS = "clock_seconds";
+ private boolean mClockVisibleByPolicy = true;
+ private boolean mClockVisibleByUser = true;
+
private boolean mAttached;
private Calendar mCalendar;
private String mClockFormatString;
@@ -110,6 +123,8 @@
null, Dependency.get(Dependency.TIME_TICK_HANDLER));
Dependency.get(TunerService.class).addTunable(this, CLOCK_SECONDS,
StatusBarIconController.ICON_BLACKLIST);
+ SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
+ Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this);
}
// NOTE: It's safe to do these after registering the receiver since the receiver always runs
@@ -130,6 +145,9 @@
getContext().unregisterReceiver(mIntentReceiver);
mAttached = false;
Dependency.get(TunerService.class).removeTunable(this);
+ SysUiServiceProvider.getComponent(getContext(), CommandQueue.class)
+ .removeCallbacks(this);
+ Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(this);
}
}
@@ -158,6 +176,22 @@
}
};
+ public void setClockVisibleByUser(boolean visible) {
+ mClockVisibleByUser = visible;
+ updateClockVisibility();
+ }
+
+ public void setClockVisibilityByPolicy(boolean visible) {
+ mClockVisibleByPolicy = visible;
+ updateClockVisibility();
+ }
+
+ private void updateClockVisibility() {
+ int visibility = (mClockVisibleByPolicy && mClockVisibleByUser)
+ ? View.VISIBLE : View.GONE;
+ setVisibility(visibility);
+ }
+
final void updateClock() {
if (mDemoMode) return;
mCalendar.setTimeInMillis(System.currentTimeMillis());
@@ -170,9 +204,38 @@
if (CLOCK_SECONDS.equals(key)) {
mShowSeconds = newValue != null && Integer.parseInt(newValue) != 0;
updateShowSeconds();
+ } else {
+ setClockVisibleByUser(!StatusBarIconController.getIconBlacklist(newValue)
+ .contains("clock"));
+ updateClockVisibility();
}
}
+ @Override
+ public void disable(int state1, int state2, boolean animate) {
+ boolean clockVisibleByPolicy = (state1 & StatusBarManager.DISABLE_CLOCK) == 0;
+ if (clockVisibleByPolicy != mClockVisibleByPolicy) {
+ setClockVisibilityByPolicy(clockVisibleByPolicy);
+ }
+ }
+
+ @Override
+ public void onDarkChanged(Rect area, float darkIntensity, int tint) {
+ setTextColor(DarkIconDispatcher.getTint(area, this, tint));
+ }
+
+ @Override
+ public void onDensityOrFontScaleChanged() {
+ FontSizeUtils.updateFontSize(this, R.dimen.status_bar_clock_size);
+ setPaddingRelative(
+ mContext.getResources().getDimensionPixelSize(
+ R.dimen.status_bar_clock_starting_padding),
+ 0,
+ mContext.getResources().getDimensionPixelSize(
+ R.dimen.status_bar_clock_end_padding),
+ 0);
+ }
+
private void updateShowSeconds() {
if (mShowSeconds) {
// Wait until we have a display to start trying to show seconds.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
new file mode 100644
index 0000000..788fda8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
@@ -0,0 +1,31 @@
+/*
+ * 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.policy;
+
+import android.content.res.Configuration;
+
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+
+/**
+ * Common listener for configuration or subsets of configuration changes (like density or
+ * font scaling), providing easy static dependence on these events.
+ */
+public interface ConfigurationController extends CallbackController<ConfigurationListener> {
+
+ interface ConfigurationListener {
+ default void onConfigChanged(Configuration newConfig) {}
+ default void onDensityOrFontScaleChanged() {}
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DarkIconDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DarkIconDispatcher.java
new file mode 100644
index 0000000..58944c6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DarkIconDispatcher.java
@@ -0,0 +1,92 @@
+/*
+ * 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.policy;
+
+import android.graphics.Color;
+import android.graphics.Rect;
+import android.view.View;
+import android.widget.ImageView;
+
+import com.android.systemui.statusbar.phone.LightBarTransitionsController;
+
+public interface DarkIconDispatcher {
+
+ void setIconsDarkArea(Rect r);
+ LightBarTransitionsController getTransitionsController();
+
+ void addDarkReceiver(DarkReceiver receiver);
+ void addDarkReceiver(ImageView imageView);
+
+ // Must have been previously been added through one of the addDarkReceive methods above.
+ void removeDarkReceiver(DarkReceiver object);
+ void removeDarkReceiver(ImageView object);
+
+ // Used to reapply darkness on an object, must have previously been added through
+ // addDarkReceiver.
+ void applyDark(ImageView object);
+
+ int DEFAULT_ICON_TINT = Color.WHITE;
+ Rect sTmpRect = new Rect();
+ int[] sTmpInt2 = new int[2];
+
+ /**
+ * @return the tint to apply to {@param view} depending on the desired tint {@param color} and
+ * the screen {@param tintArea} in which to apply that tint
+ */
+ static int getTint(Rect tintArea, View view, int color) {
+ if (isInArea(tintArea, view)) {
+ return color;
+ } else {
+ return DEFAULT_ICON_TINT;
+ }
+ }
+
+ /**
+ * @return the dark intensity to apply to {@param view} depending on the desired dark
+ * {@param intensity} and the screen {@param tintArea} in which to apply that intensity
+ */
+ static float getDarkIntensity(Rect tintArea, View view, float intensity) {
+ if (isInArea(tintArea, view)) {
+ return intensity;
+ } else {
+ return 0f;
+ }
+ }
+
+ /**
+ * @return true if more than half of the {@param view} area are in {@param area}, false
+ * otherwise
+ */
+ static boolean isInArea(Rect area, View view) {
+ if (area.isEmpty()) {
+ return true;
+ }
+ sTmpRect.set(area);
+ view.getLocationOnScreen(sTmpInt2);
+ int left = sTmpInt2[0];
+
+ int intersectStart = Math.max(left, area.left);
+ int intersectEnd = Math.min(left + view.getWidth(), area.right);
+ int intersectAmount = Math.max(0, intersectEnd - intersectStart);
+
+ boolean coversFullStatusBar = area.top <= 0;
+ boolean majorityOfWidth = 2 * intersectAmount > view.getWidth();
+ return majorityOfWidth && coversFullStatusBar;
+ }
+
+ interface DarkReceiver {
+ void onDarkChanged(Rect area, float darkIntensity, int tint);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index de47267..728005d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -21,8 +21,12 @@
boolean isSecure();
boolean canSkipBouncer();
boolean isShowing();
+ boolean isKeyguardFadingAway();
+ boolean isKeyguardGoingAway();
+ long getKeyguardFadingAwayDuration();
+ long getKeyguardFadingAwayDelay();
public interface Callback {
- void onKeyguardChanged();
+ void onKeyguardShowingChanged();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index 769f93f..821e635 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -18,13 +18,10 @@
import android.app.ActivityManager;
import android.content.Context;
-import android.os.RemoteException;
-import android.view.WindowManagerGlobal;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.settings.CurrentUserTracker;
-import com.android.systemui.statusbar.policy.KeyguardMonitor.Callback;
import java.util.ArrayList;
@@ -44,6 +41,10 @@
private boolean mCanSkipBouncer;
private boolean mListening;
+ private boolean mKeyguardFadingAway;
+ private long mKeyguardFadingAwayDelay;
+ private long mKeyguardFadingAwayDuration;
+ private boolean mKeyguardGoingAway;
public KeyguardMonitorImpl(Context context) {
mContext = context;
@@ -115,8 +116,42 @@
}
private void notifyKeyguardChanged() {
- for (Callback callback : mCallbacks) {
- callback.onKeyguardChanged();
- }
+ mCallbacks.forEach(Callback::onKeyguardShowingChanged);
+ }
+
+ public void notifyKeyguardFadingAway(long delay, long fadeoutDuration) {
+ mKeyguardFadingAway = true;
+ mKeyguardFadingAwayDelay = delay;
+ mKeyguardFadingAwayDuration = fadeoutDuration;
+ mCallbacks.forEach(Callback::onKeyguardShowingChanged);
+ }
+
+ public void notifyKeyguardDoneFading() {
+ mKeyguardFadingAway = false;
+ mCallbacks.forEach(Callback::onKeyguardShowingChanged);
+ }
+
+ @Override
+ public boolean isKeyguardFadingAway() {
+ return mKeyguardFadingAway;
+ }
+
+ @Override
+ public boolean isKeyguardGoingAway() {
+ return mKeyguardGoingAway;
+ }
+
+ @Override
+ public long getKeyguardFadingAwayDelay() {
+ return mKeyguardFadingAwayDelay;
+ }
+
+ @Override
+ public long getKeyguardFadingAwayDuration() {
+ return mKeyguardFadingAwayDuration;
+ }
+
+ public void notifyKeyguardGoingAway(boolean keyguardGoingAway) {
+ mKeyguardGoingAway = keyguardGoingAway;
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 7a32bf1..6df4a21 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -850,7 +850,7 @@
private final KeyguardMonitor.Callback mCallback = new KeyguardMonitor.Callback() {
@Override
- public void onKeyguardChanged() {
+ public void onKeyguardShowingChanged() {
notifyAdapters();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
index f195f7a..8777aa6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
@@ -36,14 +36,14 @@
int getCurrentUser();
boolean isVolumeRestricted();
- public static class Callback {
- public void onZenChanged(int zen) {}
- public void onConditionsChanged(Condition[] conditions) {}
- public void onNextAlarmChanged() {}
- public void onZenAvailableChanged(boolean available) {}
- public void onEffectsSupressorChanged() {}
- public void onManualRuleChanged(ZenRule rule) {}
- public void onConfigChanged(ZenModeConfig config) {}
+ public static interface Callback {
+ default void onZenChanged(int zen) {}
+ default void onConditionsChanged(Condition[] conditions) {}
+ default void onNextAlarmChanged() {}
+ default void onZenAvailableChanged(boolean available) {}
+ default void onEffectsSupressorChanged() {}
+ default void onManualRuleChanged(ZenRule rule) {}
+ default void onConfigChanged(ZenModeConfig config) {}
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index 489c05b..0edff86 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -42,6 +42,9 @@
import com.android.systemui.DemoMode;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.SystemUI;
+import com.android.systemui.SystemUIApplication;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.SystemUIDialog;
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index 6d62435..41b75ff 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -35,6 +35,7 @@
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
<uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
<uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" />
+ <uses-permission android:name="android.permission.CONTROL_VPN" />
<application>
<uses-library android:name="android.test.runner" />
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 81a50d9..12a485e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -18,11 +18,12 @@
import static org.mockito.Mockito.mock;
import android.content.Context;
-import android.support.test.InstrumentationRegistry;
import android.os.Handler;
import android.os.Looper;
import android.os.MessageQueue;
+import android.support.test.InstrumentationRegistry;
import android.util.ArrayMap;
+import android.util.Log;
import com.android.systemui.utils.TestableContext;
import com.android.systemui.utils.leaks.Tracker;
@@ -30,17 +31,21 @@
import org.junit.After;
import org.junit.Before;
+import java.lang.Thread.UncaughtExceptionHandler;
+
/**
* Base class that does System UI specific setup.
*/
public abstract class SysuiTestCase {
+ private Throwable mException;
private Handler mHandler;
protected TestableContext mContext;
protected TestDependency mDependency;
@Before
public void SysuiSetup() throws Exception {
+ mException = null;
System.setProperty("dexmaker.share_classloader", "true");
mContext = new TestableContext(InstrumentationRegistry.getTargetContext(), this);
SystemUIFactory.createFromConfig(mContext);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index f22c1af..9eac0a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -24,14 +24,18 @@
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.LayoutInflaterBuilder;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+import android.widget.FrameLayout;
@RunWith(AndroidJUnit4.class)
public class QSFragmentTest extends FragmentTestCase {
@@ -42,6 +46,13 @@
@Before
public void addLeakCheckDependencies() {
+ mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE,
+ new LayoutInflaterBuilder(mContext)
+ .replace("com.android.systemui.statusbar.policy.SplitClockView",
+ FrameLayout.class)
+ .replace("TextClock", View.class)
+ .build());
+
injectTestDependency(Dependency.BG_LOOPER, Looper.getMainLooper());
injectMockDependency(UserSwitcherController.class);
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index 5b22986..930e560 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -41,6 +41,7 @@
mCommandQueue = new CommandQueue();
mCallbacks = mock(Callbacks.class);
mCommandQueue.addCallbacks(mCallbacks);
+ verify(mCallbacks).disable(eq(0), eq(0), eq(false));
}
@After
@@ -181,7 +182,7 @@
public void testAppTransitionPending() {
mCommandQueue.appTransitionPending();
waitForIdleSync();
- verify(mCallbacks).appTransitionPending();
+ verify(mCallbacks).appTransitionPending(eq(false));
}
@Test
@@ -195,7 +196,7 @@
public void testAppTransitionStarting() {
mCommandQueue.appTransitionStarting(1, 2);
waitForIdleSync();
- verify(mCallbacks).appTransitionStarting(eq(1L), eq(2L));
+ verify(mCallbacks).appTransitionStarting(eq(1L), eq(2L), eq(false));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
new file mode 100644
index 0000000..cb30df4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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 org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.StatusBarManager;
+import android.view.View;
+import android.view.ViewPropertyAnimator;
+
+import com.android.systemui.FragmentTestCase;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.SecurityController;
+import com.android.systemui.tuner.TunerService;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class CollapsedStatusBarFragmentTest extends FragmentTestCase {
+
+ private NotificationIconAreaController mMockNotificiationAreaController;
+ private View mNotificationAreaInner;
+
+ public CollapsedStatusBarFragmentTest() {
+ super(CollapsedStatusBarFragment.class);
+ }
+
+ @Before
+ public void setup() {
+ mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
+ mContext.putComponent(StatusBar.class, mock(StatusBar.class));
+ mContext.putComponent(TunerService.class, mock(TunerService.class));
+ injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
+ mMockNotificiationAreaController = mock(NotificationIconAreaController.class);
+ mNotificationAreaInner = mock(View.class);
+ when(mNotificationAreaInner.animate()).thenReturn(mock(ViewPropertyAnimator.class));
+ when(mMockNotificiationAreaController.getNotificationInnerAreaView()).thenReturn(
+ mNotificationAreaInner);
+ }
+
+ @Test
+ public void testDisableNone() throws Exception {
+ postAndWait(() -> mFragments.dispatchResume());
+
+ CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ fragment.initNotificationIconArea(mMockNotificiationAreaController);
+ fragment.disable(0, 0, false);
+
+ assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
+ .getVisibility());
+ }
+
+ @Test
+ public void testDisableSystemInfo() throws Exception {
+ postAndWait(() -> mFragments.dispatchResume());
+
+ CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ fragment.initNotificationIconArea(mMockNotificiationAreaController);
+ fragment.disable(StatusBarManager.DISABLE_SYSTEM_INFO, 0, false);
+
+ assertEquals(View.INVISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
+ .getVisibility());
+
+ fragment.disable(0, 0, false);
+
+ assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
+ .getVisibility());
+ }
+
+ @Test
+ public void testDisableNotifications() throws Exception {
+ postAndWait(() -> mFragments.dispatchResume());
+
+ CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
+ fragment.initNotificationIconArea(mMockNotificiationAreaController);
+ fragment.disable(StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
+
+ Mockito.verify(mNotificationAreaInner).setVisibility(eq(View.INVISIBLE));
+
+ fragment.disable(0, 0, false);
+
+ Mockito.verify(mNotificationAreaInner).setVisibility(eq(View.VISIBLE));
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index a9d6df7..3bce64f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -15,10 +15,14 @@
package com.android.systemui.statusbar.phone;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import android.content.Context;
+import android.os.Looper;
+import android.view.Display;
import android.view.WindowManager;
+import com.android.systemui.Dependency;
import com.android.systemui.FragmentTestCase;
import com.android.systemui.recents.Recents;
import com.android.systemui.stackdivider.Divider;
@@ -35,17 +39,21 @@
@Before
public void setup() {
+ injectTestDependency(Dependency.BG_LOOPER, Looper.getMainLooper());
mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
mContext.putComponent(StatusBar.class, mock(StatusBar.class));
mContext.putComponent(Recents.class, mock(Recents.class));
mContext.putComponent(Divider.class, mock(Divider.class));
- mContext.addMockSystemService(Context.WINDOW_SERVICE, mock(WindowManager.class));
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
+ WindowManager windowManager = mock(WindowManager.class);
+ Display defaultDisplay = mContext.getSystemService(WindowManager.class).getDefaultDisplay();
+ when(windowManager.getDefaultDisplay()).thenReturn(
+ defaultDisplay);
+ mContext.addMockSystemService(Context.WINDOW_SERVICE, windowManager);
}
@Test
public void testHomeLongPress() {
- mContext.addMockSystemService(Context.WINDOW_SERVICE, mock(WindowManager.class));
NavigationBarFragment navigationBarFragment = (NavigationBarFragment) mFragment;
postAndWait(() -> mFragments.dispatchResume());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java b/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java
index 62c007f..c4f1003 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/TestableContext.java
@@ -30,6 +30,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.util.ArrayMap;
+import android.view.LayoutInflater;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.utils.leaks.Tracker;
@@ -99,6 +100,9 @@
if (mMockSystemServices != null && mMockSystemServices.containsKey(name)) {
return mMockSystemServices.get(name);
}
+ if (name.equals(LAYOUT_INFLATER_SERVICE)) {
+ return getBaseContext().getSystemService(LayoutInflater.class).cloneInContext(this);
+ }
return super.getSystemService(name);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
index 39bbf2d..21871fc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
@@ -45,6 +45,26 @@
}
@Override
+ public boolean isKeyguardFadingAway() {
+ return false;
+ }
+
+ @Override
+ public boolean isKeyguardGoingAway() {
+ return false;
+ }
+
+ @Override
+ public long getKeyguardFadingAwayDuration() {
+ return 0;
+ }
+
+ @Override
+ public long getKeyguardFadingAwayDelay() {
+ return 0;
+ }
+
+ @Override
public boolean canSkipBouncer() {
return false;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
new file mode 100644
index 0000000..b13535f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java
@@ -0,0 +1,62 @@
+/*
+ * 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.utils.leaks;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager;
+
+public class FakeStatusBarIconController extends BaseLeakChecker<IconManager>
+ implements StatusBarIconController {
+
+ public FakeStatusBarIconController(LeakCheckedTest test) {
+ super(test, "StatusBarGroup");
+ }
+
+ @Override
+ public void addIconGroup(IconManager iconManager) {
+ addCallback(iconManager);
+ }
+
+ @Override
+ public void removeIconGroup(IconManager iconManager) {
+ removeCallback(iconManager);
+ }
+
+ @Override
+ public void setExternalIcon(String slot) {
+
+ }
+
+ @Override
+ public void setIcon(String slot, int resourceId, CharSequence contentDescription) {
+
+ }
+
+ @Override
+ public void setIcon(String slot, StatusBarIcon icon) {
+
+ }
+
+ @Override
+ public void setIconVisibility(String slotTty, boolean b) {
+
+ }
+
+ @Override
+ public void removeIcon(String slot) {
+
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
index c2048c7..6ff8098 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/LeakCheckedTest.java
@@ -22,6 +22,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.statusbar.phone.ManagedProfileController;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CallbackController;
@@ -75,6 +76,7 @@
NetworkController.class,
PluginManager.class,
TunerService.class,
+ StatusBarIconController.class,
};
@Rule
@@ -121,6 +123,8 @@
obj = new FakePluginManager(mContext, this);
} else if (cls == TunerService.class) {
obj = new FakeTunerService(mContext, this);
+ } else if (cls == StatusBarIconController.class) {
+ obj = new FakeStatusBarIconController(this);
} else {
Assert.fail(cls.getName() + " is not supported by LeakCheckedTest yet");
}