diff options
Diffstat (limited to 'packages/SystemUI/src')
21 files changed, 408 insertions, 172 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java index e2b377737dbe..147162232155 100644 --- a/packages/SystemUI/src/com/android/systemui/Prefs.java +++ b/packages/SystemUI/src/com/android/systemui/Prefs.java @@ -44,6 +44,10 @@ public final class Prefs { Key.DND_NONE_SELECTED, Key.DND_FAVORITE_ZEN, Key.TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN, + Key.QS_HOTSPOT_ADDED, + Key.QS_DATA_SAVER_ADDED, + Key.QS_INVERT_COLORS_ADDED, + Key.QS_WORK_ADDED, }) public @interface Key { String OVERVIEW_SEARCH_APP_WIDGET_ID = "searchAppWidgetId"; @@ -60,6 +64,10 @@ public final class Prefs { String DND_NONE_SELECTED = "DndNoneSelected"; String DND_FAVORITE_ZEN = "DndFavoriteZen"; String TV_PICTURE_IN_PICTURE_ONBOARDING_SHOWN = "TvPictureInPictureOnboardingShown"; + String QS_HOTSPOT_ADDED = "QsHotspotAdded"; + String QS_DATA_SAVER_ADDED = "QsDataSaverAdded"; + String QS_INVERT_COLORS_ADDED = "QsInvertColorsAdded"; + String QS_WORK_ADDED = "QsWorkAdded"; } public static boolean getBoolean(Context context, @Key String key, boolean defaultValue) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java index d79f4d4d0e26..e363b767ab9f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java @@ -32,6 +32,7 @@ import android.view.ViewGroup; import com.android.settingslib.RestrictedLockUtils; import com.android.systemui.qs.QSTile.State; import com.android.systemui.qs.external.TileServices; +import com.android.systemui.statusbar.phone.ManagedProfileController; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BluetoothController; import com.android.systemui.statusbar.policy.CastController; @@ -114,6 +115,15 @@ public abstract class QSTile<TState extends State> implements Listenable { return null; // optional } + /** + * Is a startup check whether this device currently supports this tile. + * Should not be used to conditionally hide tiles. Only checked on tile + * creation or whether should be shown in edit screen. + */ + public boolean isAvailable() { + return true; + } + public interface DetailAdapter { CharSequence getTitle(); Boolean getToggleState(); @@ -392,6 +402,7 @@ public abstract class QSTile<TState extends State> implements Listenable { TileServices getTileServices(); DisplayController getDisplayController(); void removeTile(String tileSpec); + ManagedProfileController getManagedProfileController(); public interface Callback { diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java index 29f8af21e3bb..2a10c0b39544 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java @@ -55,14 +55,14 @@ public class TileQueryHelper { private void addSystemTiles(QSTileHost host) { boolean hasColorMod = host.getDisplayController().isEnabled(); String possible = mContext.getString(R.string.quick_settings_tiles_default) - + ",hotspot,inversion,saver" + (hasColorMod ? ",colors" : ""); + + ",hotspot,inversion,saver,work" + (hasColorMod ? ",colors" : ""); String[] possibleTiles = possible.split(","); final Handler qsHandler = new Handler(host.getLooper()); final Handler mainHandler = new Handler(Looper.getMainLooper()); for (int i = 0; i < possibleTiles.length; i++) { final String spec = possibleTiles[i]; final QSTile<?> tile = host.createTile(spec); - if (tile == null) { + if (tile == null || !tile.isAvailable()) { continue; } tile.setListening(true); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index 1dce053f0ff3..c4b7944039ad 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -146,8 +146,9 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> { } } - public static boolean isSupported(Host host) { - return host.getBluetoothController().isBluetoothSupported(); + @Override + public boolean isAvailable() { + return mController.isBluetoothSupported(); } private final BluetoothController.Callback mCallback = new BluetoothController.Callback() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index c3a2ebe18303..15617c7f9c8f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -136,6 +136,11 @@ public class CellularTile extends QSTile<QSTile.SignalState> { return MetricsEvent.QS_CELLULAR; } + @Override + public boolean isAvailable() { + return mController.hasMobileDataFeature(); + } + // Remove the period from the network name public static String removeTrailingPeriod(String string) { if (string == null) return null; @@ -146,10 +151,6 @@ public class CellularTile extends QSTile<QSTile.SignalState> { return string; } - public static boolean isSupported(Host host) { - return host.getNetworkController().hasMobileDataFeature(); - } - private static final class CallbackInfo { boolean enabled; boolean wifiEnabled; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index 58872ecdb2c4..29ca06bfb878 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -179,6 +179,11 @@ public class DndTile extends QSTile<QSTile.BooleanState> { } } + @Override + public boolean isAvailable() { + return isVisible(mContext); + } + private final OnSharedPreferenceChangeListener mPrefListener = new OnSharedPreferenceChangeListener() { @Override @@ -206,10 +211,6 @@ public class DndTile extends QSTile<QSTile.BooleanState> { } }; - public static boolean isSupported(Host host) { - return isVisible(host.getContext()); - } - private final class DndDetailAdapter implements DetailAdapter, OnAttachStateChangeListener { @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java index ac4dfd54a0d4..7a58f1553bcd 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -181,6 +181,11 @@ public class WifiTile extends QSTile<QSTile.SignalState> { } } + @Override + public boolean isAvailable() { + return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI); + } + private static String removeDoubleQuotes(String string) { if (string == null) return null; final int length = string.length(); @@ -190,10 +195,6 @@ public class WifiTile extends QSTile<QSTile.SignalState> { return string; } - public static boolean isSupported(Host host) { - return host.getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI); - } - protected static final class CallbackInfo { boolean enabled; boolean connected; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java index a94973c43f7a..053a98a5ce05 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java @@ -16,40 +16,25 @@ package com.android.systemui.qs.tiles; -import android.app.ActivityManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.UserInfo; -import android.os.UserHandle; -import android.os.UserManager; - import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.MetricsProto.MetricsEvent; import com.android.systemui.R; import com.android.systemui.qs.QSTile; - -import java.util.LinkedList; -import java.util.List; +import com.android.systemui.statusbar.phone.ManagedProfileController; /** Quick settings tile: Work profile on/off */ -public class WorkModeTile extends QSTile<QSTile.BooleanState> { +public class WorkModeTile extends QSTile<QSTile.BooleanState> implements + ManagedProfileController.Callback { private final AnimationIcon mEnable = new AnimationIcon(R.drawable.ic_signal_workmode_enable_animation); private final AnimationIcon mDisable = new AnimationIcon(R.drawable.ic_signal_workmode_disable_animation); - private boolean mListening; - - private UserManager mUserManager; - private List<UserInfo> mProfiles; + private final ManagedProfileController mProfileController; public WorkModeTile(Host host) { super(host); - mUserManager = UserManager.get(mContext); - mProfiles = new LinkedList<UserInfo>(); - reloadManagedProfiles(UserHandle.USER_CURRENT); + mProfileController = host.getManagedProfileController(); } @Override @@ -58,58 +43,41 @@ public class WorkModeTile extends QSTile<QSTile.BooleanState> { } @Override - public void handleClick() { - MetricsLogger.action(mContext, getMetricsCategory(), !mState.value); - setWorkModeEnabled(!mState.value); + public void setListening(boolean listening) { + if (listening) { + mProfileController.addCallback(this); + } else { + mProfileController.removeCallback(this); + } } - private void reloadManagedProfiles(int userHandle) { - synchronized (mProfiles) { - mProfiles.clear(); - - if (userHandle == UserHandle.USER_CURRENT) { - userHandle = ActivityManager.getCurrentUser(); - } - for (UserInfo ui : mUserManager.getEnabledProfiles(userHandle)) { - if (ui.isManagedProfile()) { - mProfiles.add(ui); - } - } - } + @Override + public void handleClick() { + MetricsLogger.action(mContext, getMetricsCategory(), !mState.value); + mProfileController.setWorkModeEnabled(!mState.value); } - private boolean hasActiveProfile() { - synchronized (mProfiles) { - return mProfiles.size() > 0; - } + @Override + public boolean isAvailable() { + return mProfileController.hasActiveProfile(); } - private boolean isWorkModeEnabled() { - synchronized (mProfiles) { - for (UserInfo ui : mProfiles) { - if (ui.isQuietModeEnabled()) { - return false; - } - } - return true; - } + @Override + public void onManagedProfileChanged() { + refreshState(mProfileController.isWorkModeEnabled()); } - private void refreshQuietModeState(boolean backgroundRefresh) { - refreshState(isWorkModeEnabled()); + @Override + public void onManagedProfileRemoved() { + mHost.removeTile(getTileSpec()); } @Override protected void handleUpdateState(BooleanState state, Object arg) { - if (!hasActiveProfile()) { - mHost.removeTile(getTileSpec()); - return; - } - if (arg instanceof Boolean) { state.value = (Boolean) arg; } else { - state.value = isWorkModeEnabled(); + state.value = mProfileController.isWorkModeEnabled(); } state.label = mContext.getString(R.string.quick_settings_work_mode_label); @@ -137,64 +105,4 @@ public class WorkModeTile extends QSTile<QSTile.BooleanState> { return mContext.getString(R.string.accessibility_quick_settings_work_mode_changed_off); } } - - @Override - public void setListening(boolean listening) { - if (mListening == listening) { - return; - } - mListening = listening; - if (listening) { - reloadManagedProfiles(UserHandle.USER_CURRENT); - - final IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_USER_SWITCHED); - filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED); - filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED); - filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED); - mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null); - } else { - mContext.unregisterReceiver(mReceiver); - } - } - - private void setWorkModeEnabled(boolean enabled) { - synchronized (mProfiles) { - for (UserInfo ui : mProfiles) { - mUserManager.setQuietModeEnabled(ui.id, !enabled); - } - } - } - - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - final int targetUser; - final boolean isBackgroundRefresh; - switch (action) { - case Intent.ACTION_USER_SWITCHED: - targetUser = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, - UserHandle.USER_CURRENT); - isBackgroundRefresh = true; - break; - case Intent.ACTION_MANAGED_PROFILE_ADDED: - case Intent.ACTION_MANAGED_PROFILE_REMOVED: - targetUser = UserHandle.USER_CURRENT; - isBackgroundRefresh = true; - break; - case Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED: - targetUser = UserHandle.USER_CURRENT; - isBackgroundRefresh = false; - break; - default: - targetUser = UserHandle.USER_NULL; - isBackgroundRefresh = false; - } - if (targetUser != UserHandle.USER_NULL) { - reloadManagedProfiles(targetUser); - refreshQuietModeState(isBackgroundRefresh); - } - } - }; } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 3f482c82011a..3b49d3785384 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -205,7 +205,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD ? stack.indexOfStackTask(launchTarget) : 0; boolean hasNavBarScrim = (taskCount > 0) && !config.hasTransposedNavBar; - boolean animateNavBarScrim = true; + boolean animateNavBarScrim = !launchState.launchedWhileDocking; mScrimViews.prepareEnterRecentsAnimation(hasNavBarScrim, animateNavBarScrim); // Keep track of whether we launched from the nav bar button or via alt-tab @@ -460,13 +460,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD // wait on the system to send a signal that was never queued. RecentsConfiguration config = Recents.getConfiguration(); RecentsActivityLaunchState launchState = config.getLaunchState(); - launchState.launchedFromHome = false; - launchState.launchedFromSearchHome = false; - launchState.launchedFromAppWithThumbnail = false; - launchState.launchedToTaskId = -1; - launchState.launchedWithAltTab = false; - launchState.launchedHasConfigurationChanged = false; - launchState.launchedViaDragGesture = false; + launchState.reset(); MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java index 177e8417f3fb..f7ebd945f761 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java @@ -34,10 +34,22 @@ public class RecentsActivityLaunchState { public boolean launchedReuseTaskStackViews; public boolean launchedHasConfigurationChanged; public boolean launchedViaDragGesture; + public boolean launchedWhileDocking; public int launchedToTaskId; public int launchedNumVisibleTasks; public int launchedNumVisibleThumbnails; + public void reset() { + launchedFromHome = false; + launchedFromSearchHome = false; + launchedFromAppWithThumbnail = false; + launchedToTaskId = -1; + launchedWithAltTab = false; + launchedHasConfigurationChanged = false; + launchedViaDragGesture = false; + launchedWhileDocking = false; + } + /** Called when the configuration has changed, and we want to reset any configuration specific * members. */ public void updateOnConfigurationChange() { @@ -46,6 +58,7 @@ public class RecentsActivityLaunchState { // Set this flag to indicate that the configuration has changed since Recents last launched launchedHasConfigurationChanged = true; launchedViaDragGesture = false; + launchedWhileDocking = false; } /** diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index dd7b7c1b89e6..5890b5f959d3 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -161,6 +161,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener boolean mCanReuseTaskStackViews = true; boolean mDraggingInRecents; boolean mReloadTasks; + boolean mLaunchedWhileDocking; // Task launching Rect mSearchBarBounds = new Rect(); @@ -270,10 +271,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, - boolean animate, boolean reloadTasks) { + boolean animate, boolean launchedWhileDockingTask) { mTriggeredFromAltTab = triggeredFromAltTab; mDraggingInRecents = draggingInRecents; - mReloadTasks = reloadTasks; + mLaunchedWhileDocking = launchedWhileDockingTask; if (mFastAltTabTrigger.hasTriggered()) { // We are calling this from the doze trigger, so just fall through to show Recents mFastAltTabTrigger.resetTrigger(); @@ -338,6 +339,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } mDraggingInRecents = false; + mLaunchedWhileDocking = false; mTriggeredFromAltTab = false; try { @@ -865,11 +867,11 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we // should always preload the tasks now. If we are dragging in recents, reload them as // the stacks might have changed. - if (mReloadTasks || mTriggeredFromAltTab ||sInstanceLoadPlan == null) { + if (mLaunchedWhileDocking || mTriggeredFromAltTab ||sInstanceLoadPlan == null) { // Create a new load plan if preloadRecents() was never triggered sInstanceLoadPlan = loader.createLoadPlan(mContext); } - if (mReloadTasks || mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) { + if (mLaunchedWhileDocking || mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) { loader.preloadTasks(sInstanceLoadPlan, topTask.id, isTopTaskHome); } TaskStack stack = sInstanceLoadPlan.getTaskStack(); @@ -957,6 +959,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener launchState.launchedNumVisibleThumbnails = vr.numVisibleThumbnails; launchState.launchedHasConfigurationChanged = false; launchState.launchedViaDragGesture = mDraggingInRecents; + launchState.launchedWhileDocking = mLaunchedWhileDocking; Intent intent = new Intent(); intent.setClassName(RECENTS_PACKAGE, mRecentsIntentActivityName); diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java index fb86214b04d5..42ebfa95c662 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java @@ -287,13 +287,7 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener { // wait on the system to send a signal that was never queued. RecentsConfiguration config = Recents.getConfiguration(); RecentsActivityLaunchState launchState = config.getLaunchState(); - launchState.launchedFromHome = false; - launchState.launchedFromSearchHome = false; - launchState.launchedFromAppWithThumbnail = false; - launchState.launchedToTaskId = -1; - launchState.launchedWithAltTab = false; - launchState.launchedHasConfigurationChanged = false; - launchState.launchedViaDragGesture = false; + launchState.reset(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index 5e113b997bce..d4624f58f09c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -185,7 +185,8 @@ public class RecentsView extends FrameLayout { // If we are already occluded by the app, then just set the default background scrim now. // Otherwise, defer until the enter animation completes to animate the scrim with the // tasks for the home animation. - if (launchState.launchedFromAppWithThumbnail || mStack.getTaskCount() == 0) { + if (launchState.launchedWhileDocking || launchState.launchedFromAppWithThumbnail + || mStack.getTaskCount() == 0) { mBackgroundScrim.setAlpha((int) (DEFAULT_SCRIM_ALPHA * 255)); } else { mBackgroundScrim.setAlpha(0); @@ -645,7 +646,8 @@ public class RecentsView extends FrameLayout { public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) { RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState(); - if (!launchState.launchedFromAppWithThumbnail && mStack.getTaskCount() > 0) { + if (!launchState.launchedWhileDocking && !launchState.launchedFromAppWithThumbnail + && mStack.getTaskCount() > 0) { animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, TaskStackAnimationHelper.ENTER_FROM_HOME_TRANSLATION_DURATION); } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java index 12e271397fba..36cfac8dd092 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerHandleView.java @@ -73,6 +73,7 @@ public class DividerHandleView extends ImageButton { private int mCurrentWidth; private int mCurrentHeight; private AnimatorSet mAnimator; + private boolean mTouching; public DividerHandleView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); @@ -86,6 +87,9 @@ public class DividerHandleView extends ImageButton { } public void setTouching(boolean touching, boolean animate) { + if (touching == mTouching) { + return; + } if (mAnimator != null) { mAnimator.cancel(); mAnimator = null; @@ -103,6 +107,7 @@ public class DividerHandleView extends ImageButton { animateToTarget(touching ? mCircleDiameter : mWidth, touching ? mCircleDiameter : mHeight, touching); } + mTouching = touching; } private void animateToTarget(int targetWidth, int targetHeight, boolean touching) { diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 83c22b110433..1bdf5a1e698d 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -100,6 +100,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, private final int[] mTempInt2 = new int[2]; private boolean mMoving; private int mTouchSlop; + private boolean mBackgroundLifted; private int mDividerInsets; private int mDisplayWidth; @@ -210,8 +211,8 @@ public class DividerView extends FrameLayout implements OnTouchListener, mDockSide = mWindowManagerProxy.getDockSide(); initializeSnapAlgorithm(); mWindowManagerProxy.setResizing(true); - mWindowManager.setSlippery(false); if (touching) { + mWindowManager.setSlippery(false); liftBackground(); } return mDockSide != WindowManager.DOCKED_INVALID; @@ -389,6 +390,9 @@ public class DividerView extends FrameLayout implements OnTouchListener, } private void liftBackground() { + if (mBackgroundLifted) { + return; + } if (isHorizontalDivision()) { mBackground.animate().scaleY(1.4f); } else { @@ -407,9 +411,13 @@ public class DividerView extends FrameLayout implements OnTouchListener, .setDuration(TOUCH_ANIMATION_DURATION) .translationZ(mTouchElevation) .start(); + mBackgroundLifted = true; } private void releaseBackground() { + if (!mBackgroundLifted) { + return; + } mBackground.animate() .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) .setDuration(TOUCH_RELEASE_ANIMATION_DURATION) @@ -422,6 +430,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, .setDuration(TOUCH_RELEASE_ANIMATION_DURATION) .translationZ(0) .start(); + mBackgroundLifted = false; } @Override @@ -485,7 +494,9 @@ public class DividerView extends FrameLayout implements OnTouchListener, } // Make sure shadows are updated - mBackground.invalidate(); + if (mBackground.getZ() > 0f) { + mBackground.invalidate(); + } mLastResizeRect.set(mDockedRect); if (taskPosition != TASK_POSITION_SAME) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index 333e4ff30d36..7d37ad22223f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -2097,7 +2097,7 @@ public abstract class BaseStatusBar extends SystemUI implements } - if (mNotificationData.shouldSuppressPeek(sbn.getKey())) { + if (mNotificationData.shouldSuppressScreenOn(sbn.getKey())) { if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey()); return false; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java index 3cc1ab9b42ef..2cacb8aedd65 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java @@ -283,11 +283,11 @@ public class NotificationData { return Ranking.VISIBILITY_NO_OVERRIDE; } - public boolean shouldSuppressPeek(String key) { + public boolean shouldSuppressScreenOff(String key) { if (mRankingMap != null) { mRankingMap.getRanking(key, mTmpRanking); return (mTmpRanking.getSuppressedVisualEffects() - & NotificationListenerService.SUPPRESSED_EFFECT_PEEK) != 0; + & NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF) != 0; } return false; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java new file mode 100644 index 000000000000..b74247960fc7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2016 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.os.Handler; +import android.provider.Settings.Secure; +import com.android.systemui.Prefs; +import com.android.systemui.Prefs.Key; +import com.android.systemui.qs.SecureSetting; +import com.android.systemui.statusbar.policy.DataSaverController; +import com.android.systemui.statusbar.policy.DataSaverController.Listener; +import com.android.systemui.statusbar.policy.HotspotController; +import com.android.systemui.statusbar.policy.HotspotController.Callback; + +/** + * Manages which tiles should be automatically added to QS. + */ +public class AutoTileManager { + + private final Context mContext; + private final QSTileHost mHost; + private final Handler mHandler; + + public AutoTileManager(Context context, QSTileHost host) { + mContext = context; + mHost = host; + mHandler = new Handler(mHost.getLooper()); + if (!Prefs.getBoolean(context, Key.QS_HOTSPOT_ADDED, false)) { + host.getHotspotController().addCallback(mHotspotCallback); + } + if (!Prefs.getBoolean(context, Key.QS_DATA_SAVER_ADDED, false)) { + host.getNetworkController().getDataSaverController().addListener(mDataSaverListener); + } + if (!Prefs.getBoolean(context, Key.QS_INVERT_COLORS_ADDED, false)) { + mColorsSetting = new SecureSetting(mContext, mHandler, + Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED) { + @Override + protected void handleValueChanged(int value, boolean observedChange) { + if (value != 0) { + mHost.addTile("inversion"); + Prefs.putBoolean(mContext, Key.QS_INVERT_COLORS_ADDED, true); + mHandler.post(new Runnable() { + @Override + public void run() { + mColorsSetting.setListening(false); + } + }); + } + } + }; + mColorsSetting.setListening(true); + } + if (!Prefs.getBoolean(context, Key.QS_WORK_ADDED, false)) { + host.getManagedProfileController().addCallback(mProfileCallback); + } + } + + public void destroy() { + // TODO: Remove any registered listeners. + } + + private final ManagedProfileController.Callback mProfileCallback = + new ManagedProfileController.Callback() { + @Override + public void onManagedProfileChanged() { + if (mHost.getManagedProfileController().hasActiveProfile()) { + mHost.addTile("work"); + Prefs.putBoolean(mContext, Key.QS_WORK_ADDED, true); + mHandler.post(new Runnable() { + @Override + public void run() { + mHost.getManagedProfileController().removeCallback( + mProfileCallback); + } + }); + } + } + + @Override + public void onManagedProfileRemoved() { + } + }; + + private SecureSetting mColorsSetting; + + private final DataSaverController.Listener mDataSaverListener = new Listener() { + @Override + public void onDataSaverChanged(boolean isDataSaving) { + if (isDataSaving) { + mHost.addTile("saver"); + Prefs.putBoolean(mContext, Key.QS_DATA_SAVER_ADDED, true); + mHandler.post(new Runnable() { + @Override + public void run() { + mHost.getNetworkController().getDataSaverController().remListener( + mDataSaverListener); + } + }); + } + } + }; + + private final HotspotController.Callback mHotspotCallback = new Callback() { + @Override + public void onHotspotChanged(boolean enabled) { + if (enabled) { + mHost.addTile("hotspot"); + Prefs.putBoolean(mContext, Key.QS_HOTSPOT_ADDED, true); + mHandler.post(new Runnable() { + @Override + public void run() { + mHost.getHotspotController().removeCallback(mHotspotCallback); + } + }); + } + } + }; +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java new file mode 100644 index 000000000000..63ee0c02ba63 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileController.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2016 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.app.ActivityManager; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.UserInfo; +import android.os.UserHandle; +import android.os.UserManager; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +public class ManagedProfileController { + + private final List<Callback> mCallbacks = new ArrayList<>(); + + private final Context mContext; + private final UserManager mUserManager; + private final LinkedList<UserInfo> mProfiles; + private boolean mListening; + private int mCurrentUser; + + public ManagedProfileController(QSTileHost host) { + mContext = host.getContext(); + mUserManager = UserManager.get(mContext); + mProfiles = new LinkedList<UserInfo>(); + } + + public void addCallback(Callback callback) { + mCallbacks.add(callback); + if (mCallbacks.size() == 1) { + setListening(true); + } + callback.onManagedProfileChanged(); + } + + public void removeCallback(Callback callback) { + if (mCallbacks.remove(callback) && mCallbacks.size() == 0) { + setListening(false); + } + } + + public void setWorkModeEnabled(boolean enabled) { + synchronized (mProfiles) { + for (UserInfo ui : mProfiles) { + mUserManager.setQuietModeEnabled(ui.id, !enabled); + } + } + } + + private void reloadManagedProfiles() { + synchronized (mProfiles) { + boolean hadProfile = mProfiles.size() > 0; + int user = ActivityManager.getCurrentUser(); + mProfiles.clear(); + + for (UserInfo ui : mUserManager.getEnabledProfiles(user)) { + if (ui.isManagedProfile()) { + mProfiles.add(ui); + } + } + if (mProfiles.size() == 0 && hadProfile && (user == mCurrentUser)) { + for (Callback callback : mCallbacks) { + callback.onManagedProfileRemoved(); + } + } + mCurrentUser = user; + } + } + + public boolean hasActiveProfile() { + if (!mListening) reloadManagedProfiles(); + synchronized (mProfiles) { + return mProfiles.size() > 0; + } + } + + public boolean isWorkModeEnabled() { + if (!mListening) reloadManagedProfiles(); + synchronized (mProfiles) { + for (UserInfo ui : mProfiles) { + if (ui.isQuietModeEnabled()) { + return false; + } + } + return true; + } + } + + private void setListening(boolean listening) { + mListening = listening; + if (listening) { + reloadManagedProfiles(); + + final IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_USER_SWITCHED); + filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED); + filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED); + filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED); + mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null); + } else { + mContext.unregisterReceiver(mReceiver); + } + } + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + reloadManagedProfiles(); + for (Callback callback : mCallbacks) { + callback.onManagedProfileChanged(); + } + } + }; + + public interface Callback { + void onManagedProfileChanged(); + void onManagedProfileRemoved(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index 4dee51df131c..09a7bf08ec19 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -1274,7 +1274,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } if (!isHeadsUped && notification.getNotification().fullScreenIntent != null) { - if (shouldSupressFullScreenIntent(notification.getKey())) { + if (shouldSuppressFullScreenIntent(notification.getKey())) { if (DEBUG) { Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + notification.getKey()); } @@ -1301,11 +1301,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, setAreThereNotifications(); } - private boolean shouldSupressFullScreenIntent(String key) { + private boolean shouldSuppressFullScreenIntent(String key) { if (mPowerManager.isInteractive()) { - return mNotificationData.shouldSuppressPeek(key); - } else { return mNotificationData.shouldSuppressScreenOn(key); + } else { + return mNotificationData.shouldSuppressScreenOff(key); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java index 4393e7552dd3..da2c20db6d90 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java @@ -109,6 +109,8 @@ public final class QSTileHost implements QSTile.Host, Tunable { private final List<Callback> mCallbacks = new ArrayList<>(); private final DisplayController mDisplayController; + private final AutoTileManager mAutoTiles; + private final ManagedProfileController mProfileController; private View mHeader; public QSTileHost(Context context, PhoneStatusBar statusBar, @@ -136,6 +138,7 @@ public final class QSTileHost implements QSTile.Host, Tunable { mBattery = battery; mIconController = iconController; mDisplayController = new DisplayController(mContext); + mProfileController = new ManagedProfileController(this); final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName(), Process.THREAD_PRIORITY_BACKGROUND); @@ -144,6 +147,7 @@ public final class QSTileHost implements QSTile.Host, Tunable { mServices = new TileServices(this, mLooper); + mAutoTiles = new AutoTileManager(context, this); TunerService.get(mContext).addTunable(this, TILES_SETTING); } @@ -156,6 +160,7 @@ public final class QSTileHost implements QSTile.Host, Tunable { } public void destroy() { + mAutoTiles.destroy(); TunerService.get(mContext).removeTunable(this); } @@ -290,6 +295,10 @@ public final class QSTileHost implements QSTile.Host, Tunable { return mDisplayController; } + public ManagedProfileController getManagedProfileController() { + return mProfileController; + } + @Override public void onTuningChanged(String key, String newValue) { if (!TILES_SETTING.equals(key)) { @@ -315,7 +324,7 @@ public final class QSTileHost implements QSTile.Host, Tunable { if (DEBUG) Log.d(TAG, "Creating tile: " + tileSpec); try { QSTile<?> tile = createTile(tileSpec); - if (tile != null) { + if (tile != null && tile.isAvailable()) { tile.setTileSpec(tileSpec); newTiles.put(tileSpec, tile); } @@ -341,6 +350,16 @@ public final class QSTileHost implements QSTile.Host, Tunable { TextUtils.join(",", specs), ActivityManager.getCurrentUser()); } + public void addTile(String spec) { + if (mTileSpecs.contains(spec)) { + return; + } + ArrayList<String> specs = new ArrayList<>(mTileSpecs); + specs.add(spec); + Settings.Secure.putStringForUser(mContext.getContentResolver(), TILES_SETTING, + TextUtils.join(",", specs), ActivityManager.getCurrentUser()); + } + public void addTile(ComponentName tile) { List<String> newSpecs = new ArrayList<>(mTileSpecs); newSpecs.add(0, CustomTile.toSpec(tile)); @@ -387,14 +406,10 @@ public final class QSTileHost implements QSTile.Host, Tunable { } public QSTile<?> createTile(String tileSpec) { - if (tileSpec.equals("wifi")) return WifiTile.isSupported(this) - ? new WifiTile(this) : null; - else if (tileSpec.equals("bt")) return BluetoothTile.isSupported(this) - ? new BluetoothTile(this) : null; - else if (tileSpec.equals("cell")) return CellularTile.isSupported(this) - ? new CellularTile(this) : null; - else if (tileSpec.equals("dnd")) return DndTile.isSupported(this) - ? new DndTile(this) : null; + if (tileSpec.equals("wifi")) return new WifiTile(this); + else if (tileSpec.equals("bt")) return new BluetoothTile(this); + else if (tileSpec.equals("cell")) return new CellularTile(this); + else if (tileSpec.equals("dnd")) return new DndTile(this); else if (tileSpec.equals("inversion")) return new ColorInversionTile(this); else if (tileSpec.equals("airplane")) return new AirplaneModeTile(this); else if (tileSpec.equals("work")) return new WorkModeTile(this); |