Merge "Work on separating out the status bar management"

This commit is contained in:
TreeHugger Robot
2017-02-09 02:48:33 +00:00
committed by Android (Google) Code Review
44 changed files with 1560 additions and 817 deletions

View File

@@ -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"

View File

@@ -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" />

View File

@@ -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 @@ public class BatteryMeterView extends ImageView implements
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 @@ public class BatteryMeterView extends ImageView implements
mBatteryController.removeCallback(this);
mDrawable.stopListening();
Dependency.get(TunerService.class).removeTunable(this);
Dependency.get(ConfigurationController.class).removeCallback(this);
}
@Override
@@ -99,8 +112,35 @@ public class BatteryMeterView extends ImageView implements
}
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) {

View File

@@ -25,9 +25,13 @@ import android.util.ArrayMap;
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.BluetoothController;
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 @@ public class Dependency extends SystemUI {
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);
}

View File

@@ -97,7 +97,7 @@ public class FragmentHostManager {
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 @@ public class FragmentHostManager {
if (current != null && current.getView() != null) {
listener.onFragmentViewCreated(tag, current);
}
return this;
}
// Shouldn't generally be needed, included for completeness sake.

View File

@@ -179,7 +179,7 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
}
@Override
public void onKeyguardChanged() {
public void onKeyguardShowingChanged() {
refreshState();
}
};

View File

@@ -141,7 +141,7 @@ public class LocationTile extends QSTile<QSTile.BooleanState> {
}
@Override
public void onKeyguardChanged() {
public void onKeyguardShowingChanged() {
refreshState();
}
};

View File

@@ -25,7 +25,6 @@ import android.os.Looper;
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 @@ public class CommandQueue extends IStatusBar.Stub {
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 @@ public class CommandQueue extends IStatusBar.Stub {
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 class CommandQueue extends IStatusBar.Stub {
public void addCallbacks(Callbacks callbacks) {
mCallbacks.add(callbacks);
callbacks.disable(mDisable1, mDisable2, false /* animate */);
}
public void removeCallbacks(Callbacks callbacks) {
@@ -164,6 +166,8 @@ public class CommandQueue extends IStatusBar.Stub {
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 class CommandQueue extends IStatusBar.Stub {
}
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 class CommandQueue extends IStatusBar.Stub {
}
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 @@ public class CommandQueue extends IStatusBar.Stub {
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 @@ public class CommandQueue extends IStatusBar.Stub {
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:

View File

@@ -43,6 +43,8 @@ import android.widget.LinearLayout;
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.ArrayList;
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 @@ public class SignalClusterView
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 @@ public class SignalClusterView
}
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 class SignalClusterView
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));
}
}

View File

@@ -32,17 +32,19 @@ import android.view.ViewGroup.LayoutParams;
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 @@ public class CarStatusBar extends StatusBar implements
createBatteryController();
mCarBatteryController.startListening();
mConnectedDeviceSignalController.startListening();
}
@Override
@@ -87,32 +88,40 @@ public class CarStatusBar extends StatusBar implements
}
@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() {

View File

@@ -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();
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -22,6 +22,7 @@ import android.view.View;
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 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
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 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
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);
}

View File

@@ -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 @@ import java.io.PrintWriter;
/**
* 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 class LightBarTransitionsController implements Dumpable {
}
};
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 @@ public class LightBarTransitionsController implements Dumpable {
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 @@ public class LightBarTransitionsController implements Dumpable {
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,

View File

@@ -118,7 +118,6 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
private int mSystemUiVisibility;
private LightBarController mLightBarController;
private boolean mKeyguardGoingAway;
public boolean mHomeBlockedThisTouch;
@@ -195,6 +194,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
@Override
public void onDestroyView() {
super.onDestroyView();
mNavigationBarView.getLightTransitionsController().destroy(getContext());
getContext().unregisterReceiver(mBroadcastReceiver);
}
@@ -287,31 +287,6 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
}
}
@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 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
delay + StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE);
}
public void setKeyguardGoingAway(boolean keyguardGoingAway) {
mKeyguardGoingAway = keyguardGoingAway;
}
public BarTransitions getBarTransitions() {
return mNavigationBarView.getBarTransitions();
}

View File

@@ -38,7 +38,8 @@ public final class NavigationBarTransitions extends BarTransitions {
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() {

View File

@@ -17,6 +17,8 @@ import com.android.systemui.statusbar.NotificationData;
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 @@ import java.util.function.Function;
* 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 @@ public class NotificationIconAreaController {
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 @@ public class NotificationIconAreaController {
}
/**
* 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 @@ public class NotificationIconAreaController {
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);
}

View File

@@ -166,6 +166,10 @@ public abstract class PanelBar extends FrameLayout {
if (DEBUG) LOG("onPanelPeeked");
}
public boolean isClosed() {
return mState == STATE_CLOSED;
}
public void onPanelCollapsed() {
if (DEBUG) LOG("onPanelCollapsed");
}

View File

@@ -38,24 +38,35 @@ import com.android.internal.telephony.IccCardConstants;
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 @@ public class PhoneStatusBarPolicy implements Callback, RotationLockController.Ro
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 @@ public class PhoneStatusBarPolicy implements Callback, RotationLockController.Ro
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 @@ public class PhoneStatusBarPolicy implements Callback, RotationLockController.Ro
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 @@ public class PhoneStatusBarPolicy implements Callback, RotationLockController.Ro
// 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 @@ public class PhoneStatusBarPolicy implements Callback, RotationLockController.Ro
// 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 @@ public class PhoneStatusBarPolicy implements Callback, RotationLockController.Ro
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 @@ public class PhoneStatusBarPolicy implements Callback, RotationLockController.Ro
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 class PhoneStatusBarPolicy implements Callback, RotationLockController.Ro
}
};
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();

View File

@@ -24,9 +24,13 @@ import android.view.View;
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 @@ public class PhoneStatusBarView extends PanelBar {
}
}
};
private DarkReceiver mBattery;
public PhoneStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -70,6 +75,20 @@ public class PhoneStatusBarView extends PanelBar {
@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

View File

@@ -178,7 +178,7 @@ public class QuickStatusBarHeader extends BaseStatusBarHeader implements
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);

View File

@@ -173,13 +173,16 @@ import com.android.systemui.statusbar.ScrimView;
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 @@ public class StatusBar extends SystemUI implements DemoMode,
}
updateQsExpansionEnabled();
}
if (mIconPolicy != null) {
mIconPolicy.setCurrentUserSetup(mUserSetup);
}
}
};
@@ -712,6 +712,8 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
// 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 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
// 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 @@ public class StatusBar extends SystemUI implements DemoMode,
mGroupManager.setOnGroupChangeListener(mStackScroller);
mVisualStabilityManager.setVisibilityLocationProvider(mStackScroller);
inflateShelf();
inflateEmptyShadeView();
inflateDismissView();
mExpandedContents = mStackScroller;
@@ -1025,7 +1051,6 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
// set the initial view visibility
setAreThereNotifications();
createIconController();
// TODO: Find better place for this callback.
mBatteryController.addCallback(new BatteryStateChangeCallback() {
@Override
@@ -1057,7 +1080,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
});
mLightBarController = new LightBarController(mIconController);
mLightBarController = new LightBarController();
if (mNavigationBar != null) {
mNavigationBar.setLightBarController(mLightBarController);
}
@@ -1081,7 +1104,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
mHeadsUpManager.addListener(mScrimController);
mStackScroller.setScrimController(mScrimController);
mStatusBarView.setScrimController(mScrimController);
mDozeScrimController = new DozeScrimController(mScrimController, context, mStackScroller,
mNotificationPanel);
@@ -1187,8 +1209,6 @@ public class StatusBar extends SystemUI implements DemoMode,
// 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 @@ public class StatusBar extends SystemUI implements DemoMode,
}
// 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 @@ public class StatusBar extends SystemUI implements DemoMode,
}
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 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
updateNotifications();
}
// end old BaseStatusBar.setZenMode().
if (mIconPolicy != null) {
mIconPolicy.setZenMode(mode);
}
}
protected void startKeyguard() {
@@ -1445,7 +1462,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mKeyguardIndicationController.setUserInfoController(
Dependency.get(UserInfoController.class));
mFingerprintUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mIconPolicy.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mRemoteInputController.addCallback(mStatusBarKeyguardViewManager);
mRemoteInputController.addCallback(new RemoteInputController.Callback() {
@@ -1526,16 +1542,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
@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 @@ public class StatusBar extends SystemUI implements DemoMode,
updateQsExpansionEnabled();
// Let's also update the icons
mIconController.updateNotificationIcons(mNotificationData);
mNotificationIconAreaController.updateNotificationIcons(mNotificationData);
}
/**
@@ -2079,24 +2085,26 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
&& 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 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
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 @@ public class StatusBar extends SystemUI implements DemoMode,
mFalsingManager.onScreenOff();
}
public NotificationShelf getNotificationShelf() {
return mNotificationShelf;
}
public NotificationStackScrollLayout getNotificationScrollLayout() {
return mStackScroller;
}
@@ -2757,6 +2717,14 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
}
private void finishBarAnimations() {
mStatusBarView.getBarTransitions().finishAnimations();
if (mStatusBarView != null) {
mStatusBarView.getBarTransitions().finishAnimations();
}
if (mNavigationBar != null) {
mNavigationBar.finishBarAnimations();
}
@@ -3363,8 +3334,6 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
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 @@ public class StatusBar extends SystemUI implements DemoMode,
// 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 @@ public class StatusBar extends SystemUI implements DemoMode,
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 class StatusBar extends SystemUI implements DemoMode,
public void finishKeyguardFadingAway() {
mKeyguardFadingAway = false;
mKeyguardGoingAway = false;
if (mNavigationBar != null) {
mNavigationBar.setKeyguardGoingAway(false);
}
mKeyguardMonitor.notifyKeyguardDoneFading();
}
public void stopWaitingForKeyguardExit() {
@@ -4357,7 +4299,6 @@ public class StatusBar extends SystemUI implements DemoMode,
} else {
mScrimController.setKeyguardShowing(false);
}
mIconPolicy.notifyKeyguardShowingChanged();
mNotificationPanel.setBarState(mState, mKeyguardFadingAway, goingToFullShade);
updateDozingState();
updatePublicMode();
@@ -4944,33 +4885,11 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}
@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 @@ public class StatusBar extends SystemUI implements DemoMode,
private boolean mVisibleToUser;
private Locale mLocale;
private float mFontScale;
protected boolean mUseHeadsUp = false;
protected boolean mHeadsUpTicker = false;
@@ -5197,7 +5115,6 @@ public class StatusBar extends SystemUI implements DemoMode,
private final SparseBooleanArray mUsersAllowingNotifications = new SparseBooleanArray();
private UserManager mUserManager;
private int mDensity;
protected KeyguardManager mKeyguardManager;
private LockPatternUtils mLockPatternUtils;

View File

@@ -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 @@ public class StatusBarIconController extends StatusBarIconList implements Tunabl
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();
}
@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));
}
scaleBatteryMeterViews(mContext);
}
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);
}
}
}

View File

@@ -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();
}
}

View File

@@ -22,8 +22,8 @@ import java.io.PrintWriter;
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;

View File

@@ -19,11 +19,14 @@ package com.android.systemui.statusbar.policy;
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.CharacterStyle;
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 @@ import java.util.TimeZone;
/**
* 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 @@ public class Clock extends TextView implements DemoMode, Tunable {
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 @@ public class Clock extends TextView implements DemoMode, Tunable {
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 class Clock extends TextView implements DemoMode, Tunable {
}
};
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 @@ public class Clock extends TextView implements DemoMode, Tunable {
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.

View File

@@ -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() {}
}
}

View File

@@ -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);
}
}

View File

@@ -21,8 +21,12 @@ public interface KeyguardMonitor extends CallbackController<Callback> {
boolean isSecure();
boolean canSkipBouncer();
boolean isShowing();
boolean isKeyguardFadingAway();
boolean isKeyguardGoingAway();
long getKeyguardFadingAwayDuration();
long getKeyguardFadingAwayDelay();
public interface Callback {
void onKeyguardChanged();
void onKeyguardShowingChanged();
}
}

View File

@@ -18,13 +18,10 @@ package com.android.systemui.statusbar.policy;
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 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback
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 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback
}
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;
}
}

View File

@@ -850,7 +850,7 @@ public class UserSwitcherController {
private final KeyguardMonitor.Callback mCallback = new KeyguardMonitor.Callback() {
@Override
public void onKeyguardChanged() {
public void onKeyguardShowingChanged() {
notifyAdapters();
}
};

View File

@@ -36,14 +36,14 @@ public interface ZenModeController extends CallbackController<Callback> {
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) {}
}
}

View File

@@ -42,6 +42,9 @@ import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING;
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;

View File

@@ -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" />

View File

@@ -18,11 +18,12 @@ package com.android.systemui;
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 com.android.systemui.utils.leaks.Tracker;
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);

View File

@@ -24,14 +24,18 @@ import com.android.systemui.statusbar.phone.QuickStatusBarHeader;
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 @@ public class QSFragmentTest extends FragmentTestCase {
@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);

View File

@@ -41,6 +41,7 @@ public class CommandQueueTest extends SysuiTestCase {
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 class CommandQueueTest extends SysuiTestCase {
public void testAppTransitionPending() {
mCommandQueue.appTransitionPending();
waitForIdleSync();
verify(mCallbacks).appTransitionPending();
verify(mCallbacks).appTransitionPending(eq(false));
}
@Test
@@ -195,7 +196,7 @@ public class CommandQueueTest extends SysuiTestCase {
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

View File

@@ -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));
}
}

View File

@@ -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 @@ public class NavigationBarFragmentTest extends FragmentTestCase {
@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());

View File

@@ -30,6 +30,7 @@ import android.os.IBinder;
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 @@ public class TestableContext extends ContextWrapper implements SysUiServiceProvi
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);
}

View File

@@ -44,6 +44,26 @@ public class FakeKeyguardMonitor implements KeyguardMonitor {
return false;
}
@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;

View File

@@ -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) {
}
}

View File

@@ -22,6 +22,7 @@ import android.util.ArrayMap;
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 @@ public abstract class LeakCheckedTest extends SysuiTestCase {
NetworkController.class,
PluginManager.class,
TunerService.class,
StatusBarIconController.class,
};
@Rule
@@ -121,6 +123,8 @@ public abstract class LeakCheckedTest extends SysuiTestCase {
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");
}