summaryrefslogtreecommitdiffstats
path: root/packages/SystemUI/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/SystemUI/src')
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerUI.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/UsageTracker.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java102
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Constants.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java64
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/Task.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java98
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java136
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java294
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewFooter.java98
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java70
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java216
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointController.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiAccessPointController.java)84
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java67
53 files changed, 794 insertions, 973 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index f184ad2..f5df1a9 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -43,6 +43,7 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import java.io.PrintWriter;
+import java.text.NumberFormat;
public class PowerNotificationWarnings implements PowerUI.WarningsUI {
private static final String TAG = PowerUI.TAG + ".Notification";
@@ -143,7 +144,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
showSaverNotification();
mShowing = SHOWING_SAVER;
} else {
- mNoMan.cancel(TAG_NOTIFICATION, ID_NOTIFICATION);
+ mNoMan.cancelAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, UserHandle.ALL);
mShowing = SHOWING_NOTHING;
}
}
@@ -157,7 +158,6 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
.setContentTitle(mContext.getString(R.string.invalid_charger_title))
.setContentText(mContext.getString(R.string.invalid_charger_text))
.setPriority(Notification.PRIORITY_MAX)
- .setCategory(Notification.CATEGORY_SYSTEM)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setColor(mContext.getResources().getColor(
com.android.internal.R.color.system_notification_accent_color));
@@ -165,22 +165,22 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
if (n.headsUpContentView != null) {
n.headsUpContentView.setViewVisibility(com.android.internal.R.id.right_icon, View.GONE);
}
- mNoMan.notifyAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, n, UserHandle.CURRENT);
+ mNoMan.notifyAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, n, UserHandle.ALL);
}
private void showWarningNotification() {
final int textRes = mSaver ? R.string.battery_low_percent_format_saver_started
: R.string.battery_low_percent_format;
+ final String percentage = NumberFormat.getPercentInstance().format((double) mBatteryLevel / 100.0);
final Notification.Builder nb = new Notification.Builder(mContext)
.setSmallIcon(R.drawable.ic_power_low)
// Bump the notification when the bucket dropped.
.setWhen(mBucketDroppedNegativeTimeMs)
.setShowWhen(false)
.setContentTitle(mContext.getString(R.string.battery_low_title))
- .setContentText(mContext.getString(textRes, mBatteryLevel))
+ .setContentText(mContext.getString(textRes, percentage))
.setOnlyAlertOnce(true)
.setPriority(Notification.PRIORITY_MAX)
- .setCategory(Notification.CATEGORY_SYSTEM)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setColor(mContext.getResources().getColor(
com.android.internal.R.color.battery_saver_mode_color));
@@ -202,7 +202,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
if (n.headsUpContentView != null) {
n.headsUpContentView.setViewVisibility(com.android.internal.R.id.right_icon, View.GONE);
}
- mNoMan.notifyAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, n, UserHandle.CURRENT);
+ mNoMan.notifyAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, n, UserHandle.ALL);
}
private void showSaverNotification() {
@@ -212,7 +212,6 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
.setContentText(mContext.getString(R.string.battery_saver_notification_text))
.setOngoing(true)
.setShowWhen(false)
- .setCategory(Notification.CATEGORY_SYSTEM)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setColor(mContext.getResources().getColor(
com.android.internal.R.color.battery_saver_mode_color));
@@ -220,7 +219,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
if (hasSaverSettings()) {
nb.setContentIntent(pendingActivity(mOpenSaverSettings));
}
- mNoMan.notifyAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, nb.build(), UserHandle.CURRENT);
+ mNoMan.notifyAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, nb.build(), UserHandle.ALL);
}
private void addStopSaverAction(Notification.Builder nb) {
@@ -341,6 +340,11 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
updateNotification();
}
+ @Override
+ public void userSwitched() {
+ updateNotification();
+ }
+
private void showStartSaverConfirmation() {
if (mSaverConfirmation != null) return;
final SystemUIDialog d = new SystemUIDialog(mContext);
@@ -370,7 +374,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
filter.addAction(ACTION_SHOW_BATTERY_SETTINGS);
filter.addAction(ACTION_START_SAVER);
filter.addAction(ACTION_STOP_SAVER);
- mContext.registerReceiver(this, filter, null, mHandler);
+ mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, null, mHandler);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index d3c7dee..9459740 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -137,6 +137,7 @@ public class PowerUI extends SystemUI {
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
mContext.registerReceiver(this, filter, null, mHandler);
@@ -207,6 +208,8 @@ public class PowerUI extends SystemUI {
mScreenOffTime = SystemClock.elapsedRealtime();
} else if (Intent.ACTION_SCREEN_ON.equals(action)) {
mScreenOffTime = -1;
+ } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+ mWarnings.userSwitched();
} else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)) {
updateSaverMode();
} else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGING.equals(action)) {
@@ -256,6 +259,7 @@ public class PowerUI extends SystemUI {
void updateLowBatteryWarning();
boolean isInvalidChargerWarningShowing();
void dump(PrintWriter pw);
+ void userSwitched();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java
index eb4560d..111484b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java
@@ -55,7 +55,6 @@ public class QSDetailClipper {
if (listener != null) {
mAnimator.addListener(listener);
}
- mDetail.setLayerType(View.LAYER_TYPE_HARDWARE, null);
if (in) {
mBackground.startTransition((int)(mAnimator.getDuration() * 0.6));
mAnimator.addListener(mVisibleOnStart);
@@ -82,7 +81,6 @@ public class QSDetailClipper {
}
public void onAnimationEnd(Animator animation) {
- mDetail.setLayerType(View.LAYER_TYPE_NONE, null);
mAnimator = null;
}
};
@@ -90,7 +88,6 @@ public class QSDetailClipper {
private final AnimatorListenerAdapter mGoneOnEnd = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- mDetail.setLayerType(View.LAYER_TYPE_NONE, null);
mDetail.setVisibility(View.GONE);
mBackground.resetTransition();
mAnimator = null;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index 3574877..d5c90d0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -132,6 +132,7 @@ public class QSTileView extends ViewGroup {
mDualLabel = new QSDualTileLabel(mContext);
mDualLabel.setId(android.R.id.title);
mDualLabel.setBackgroundResource(R.drawable.btn_borderless_rect);
+ mDualLabel.setFirstLineCaret(res.getDrawable(R.drawable.qs_dual_tile_caret));
mDualLabel.setTextColor(res.getColor(R.color.qs_tile_text));
mDualLabel.setPadding(0, mDualTileVerticalPaddingPx, 0, mDualTileVerticalPaddingPx);
mDualLabel.setTypeface(CONDENSED);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/UsageTracker.java b/packages/SystemUI/src/com/android/systemui/qs/UsageTracker.java
index ad79aba..a1092a3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/UsageTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/UsageTracker.java
@@ -22,7 +22,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
-import com.android.systemui.R;
import com.android.systemui.statusbar.policy.Listenable;
public class UsageTracker implements Listenable {
@@ -35,11 +34,10 @@ public class UsageTracker implements Listenable {
private boolean mRegistered;
- public UsageTracker(Context context, Class<?> tile) {
+ public UsageTracker(Context context, Class<?> tile, int timeoutResource) {
mContext = context;
mPrefKey = tile.getSimpleName() + "LastUsed";
- mTimeToShowTile = MILLIS_PER_DAY * mContext.getResources()
- .getInteger(R.integer.days_to_show_timeout_tiles);
+ mTimeToShowTile = MILLIS_PER_DAY * mContext.getResources().getInteger(timeoutResource);
mResetAction = "com.android.systemui.qs." + tile.getSimpleName() + ".usage_reset";
}
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 e99b4c5..84bfb8f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -77,7 +77,7 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
@Override
protected void handleSecondaryClick() {
- mHost.startSettingsActivity(BLUETOOTH_SETTINGS);
+ showDetail(true);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 01849c1..7ba1dc0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -44,7 +44,8 @@ public class ColorInversionTile extends QSTile<QSTile.BooleanState> {
}
}
};
- mUsageTracker = new UsageTracker(host.getContext(), ColorInversionTile.class);
+ mUsageTracker = new UsageTracker(host.getContext(), ColorInversionTile.class,
+ R.integer.days_to_show_color_inversion_tile);
if (mSetting.getValue() != 0 && !mUsageTracker.isRecentlyUsed()) {
mUsageTracker.trackUsage();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index ce99cc3..b30a1d3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -34,7 +34,7 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> {
public HotspotTile(Host host) {
super(host);
mController = host.getHotspotController();
- mUsageTracker = new UsageTracker(host.getContext(), HotspotTile.class);
+ mUsageTracker = newUsageTracker(host.getContext());
mUsageTracker.setListening(true);
}
@@ -84,6 +84,10 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> {
}
}
+ private static UsageTracker newUsageTracker(Context context) {
+ return new UsageTracker(context, HotspotTile.class, R.integer.days_to_show_hotspot_tile);
+ }
+
private final class Callback implements HotspotController.Callback {
@Override
public void onHotspotChanged(boolean enabled) {
@@ -101,7 +105,7 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> {
@Override
public void onReceive(Context context, Intent intent) {
if (mUsageTracker == null) {
- mUsageTracker = new UsageTracker(context, HotspotTile.class);
+ mUsageTracker = newUsageTracker(context);
}
mUsageTracker.trackUsage();
}
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 0985812..20c4ee8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -87,7 +87,15 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
@Override
protected void handleSecondaryClick() {
- mHost.startSettingsActivity(WIFI_SETTINGS);
+ if (!mController.canConfigWifi()) {
+ mHost.startSettingsActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
+ return;
+ }
+ if (!mState.enabled) {
+ mController.setWifiEnabled(true);
+ mState.enabled = true;
+ }
+ showDetail(true);
}
@Override
@@ -279,7 +287,9 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
if (item == null || item.tag == null) return;
final AccessPoint ap = (AccessPoint) item.tag;
if (!ap.isConnected) {
- mController.connect(ap);
+ if (mController.connect(ap)) {
+ mHost.collapsePanels();
+ }
}
showDetail(false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 1283dcd..76e8181 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -54,17 +54,15 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
/** A proxy implementation for the recents component */
-public class AlternateRecentsComponent implements ActivityOptions.OnAnimationStartedListener {
+public class AlternateRecentsComponent {
final public static String EXTRA_FROM_HOME = "recents.triggeredOverHome";
final public static String EXTRA_FROM_SEARCH_HOME = "recents.triggeredOverSearchHome";
final public static String EXTRA_FROM_APP_THUMBNAIL = "recents.animatingWithThumbnail";
- final public static String EXTRA_FROM_APP_FULL_SCREENSHOT = "recents.thumbnail";
final public static String EXTRA_FROM_TASK_ID = "recents.activeTaskId";
final public static String EXTRA_TRIGGERED_FROM_ALT_TAB = "recents.triggeredFromAltTab";
final public static String EXTRA_TRIGGERED_FROM_HOME_KEY = "recents.triggeredFromHomeKey";
- final public static String ACTION_START_ENTER_ANIMATION = "action_start_enter_animation";
final public static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
final public static String ACTION_HIDE_RECENTS_ACTIVITY = "action_hide_recents_activity";
@@ -74,15 +72,12 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
final static String sRecentsPackage = "com.android.systemui";
final static String sRecentsActivity = "com.android.systemui.recents.RecentsActivity";
- static Bitmap sLastScreenshot;
static RecentsComponent.Callbacks sRecentsComponentCallbacks;
Context mContext;
LayoutInflater mInflater;
SystemServicesProxy mSystemServicesProxy;
- Handler mHandler;
boolean mBootCompleted;
- boolean mStartAnimationTriggered;
// Task launching
RecentsConfiguration mConfig;
@@ -108,7 +103,6 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
mInflater = LayoutInflater.from(context);
mContext = context;
mSystemServicesProxy = new SystemServicesProxy(context);
- mHandler = new Handler();
mTaskStackBounds = new Rect();
}
@@ -132,6 +126,9 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
}
}
}
+
+ // When we start, preload the metadata associated with the previous tasks
+ RecentsTaskLoader.getInstance().preload(mContext);
}
public void onBootCompleted() {
@@ -256,7 +253,6 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
public void onConfigurationChanged(Configuration newConfig) {
// Reload the header bar layout
reloadHeaderBarLayout();
- sLastScreenshot = null;
}
/** Prepares the header bar layout. */
@@ -330,7 +326,8 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
// If the user has toggled it too quickly, then just eat up the event here (it's better than
// showing a janky screenshot).
// NOTE: Ideally, the screenshot mechanism would take the window transform into account
- if (System.currentTimeMillis() - mLastToggleTime < sMinToggleDelay) {
+ long currentTime = System.currentTimeMillis();
+ if ((currentTime > mLastToggleTime) && (currentTime - mLastToggleTime) < sMinToggleDelay) {
return;
}
@@ -367,47 +364,30 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
* Creates the activity options for a unknown state->recents transition.
*/
ActivityOptions getUnknownTransitionActivityOptions() {
- mStartAnimationTriggered = false;
return ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_unknown_enter,
- R.anim.recents_from_unknown_exit, mHandler, this);
+ R.anim.recents_from_unknown_exit);
}
/**
* Creates the activity options for a home->recents transition.
*/
ActivityOptions getHomeTransitionActivityOptions(boolean fromSearchHome) {
- mStartAnimationTriggered = false;
if (fromSearchHome) {
return ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_search_launcher_enter,
- R.anim.recents_from_search_launcher_exit, mHandler, this);
+ R.anim.recents_from_search_launcher_exit);
}
return ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_launcher_enter,
- R.anim.recents_from_launcher_exit, mHandler, this);
+ R.anim.recents_from_launcher_exit);
}
/**
- * Creates the activity options for an app->recents transition. If this method sets the static
- * screenshot, then we will use that for the transition.
+ * Creates the activity options for an app->recents transition.
*/
ActivityOptions getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo topTask,
boolean isTopTaskHome) {
- if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
- // Recycle the last screenshot
- consumeLastScreenshot();
-
- // Take the full screenshot
- sLastScreenshot = mSystemServicesProxy.takeAppScreenshot();
- if (sLastScreenshot != null) {
- mStartAnimationTriggered = false;
- return ActivityOptions.makeCustomAnimation(mContext,
- R.anim.recents_from_app_enter,
- R.anim.recents_from_app_exit, mHandler, this);
- }
- }
-
// Update the destination rect
Task toTask = new Task();
TaskViewTransform toTransform = getThumbnailTransitionTransform(topTask.id, isTopTaskHome,
@@ -428,10 +408,9 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
c.setBitmap(null);
}
- mStartAnimationTriggered = false;
return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mStatusBarView,
thumbnail, toTaskRect.left, toTaskRect.top, toTaskRect.width(),
- toTaskRect.height(), this);
+ toTaskRect.height(), null);
}
// If both the screenshot and thumbnail fails, then just fall back to the default transition
@@ -493,11 +472,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
// Try starting with a thumbnail transition
ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, isTopTaskHome);
if (opts != null) {
- if (sLastScreenshot != null) {
- startAlternateRecentsActivity(topTask, opts, EXTRA_FROM_APP_FULL_SCREENSHOT);
- } else {
- startAlternateRecentsActivity(topTask, opts, EXTRA_FROM_APP_THUMBNAIL);
- }
+ startAlternateRecentsActivity(topTask, opts, EXTRA_FROM_APP_THUMBNAIL);
} else {
// Fall through below to the non-thumbnail transition
useThumbnailTransition = false;
@@ -535,7 +510,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
} else {
// Otherwise we do the normal fade from an unknown source
ActivityOptions opts = getUnknownTransitionActivityOptions();
- startAlternateRecentsActivity(topTask, opts, null);
+ startAlternateRecentsActivity(topTask, opts, EXTRA_FROM_HOME);
}
}
mLastToggleTime = System.currentTimeMillis();
@@ -561,19 +536,6 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
}
}
- /** Returns the last screenshot taken, this will be called by the RecentsActivity. */
- public static Bitmap getLastScreenshot() {
- return sLastScreenshot;
- }
-
- /** Recycles the last screenshot taken, this will be called by the RecentsActivity. */
- public static void consumeLastScreenshot() {
- if (sLastScreenshot != null) {
- sLastScreenshot.recycle();
- sLastScreenshot = null;
- }
- }
-
/** Sets the RecentsComponent callbacks. */
public void setRecentsComponentCallback(RecentsComponent.Callbacks cb) {
sRecentsComponentCallbacks = cb;
@@ -585,42 +547,4 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
sRecentsComponentCallbacks.onVisibilityChanged(visible);
}
}
-
- /**** OnAnimationStartedListener Implementation ****/
-
- @Override
- public void onAnimationStarted() {
- // Notify recents to start the enter animation
- if (!mStartAnimationTriggered) {
- // There can be a race condition between the start animation callback and
- // the start of the new activity (where we register the receiver that listens
- // to this broadcast, so we add our own receiver and if that gets called, then
- // we know the activity has not yet started and we can retry sending the broadcast.
- BroadcastReceiver fallbackReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (getResultCode() == Activity.RESULT_OK) {
- mStartAnimationTriggered = true;
- return;
- }
-
- // Schedule for the broadcast to be sent again after some time
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- onAnimationStarted();
- }
- }, 75);
- }
- };
-
- // Send the broadcast to notify Recents that the animation has started
- Intent intent = new Intent(ACTION_START_ENTER_ANIMATION);
- intent.setPackage(mContext.getPackageName());
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
- Intent.FLAG_RECEIVER_FOREGROUND);
- mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
- fallbackReceiver, null, Activity.RESULT_CANCELED, null, null);
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 85cf077..9b84d2e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -25,8 +25,6 @@ public class Constants {
public static final boolean Verbose = false;
public static class App {
- // Enables the screenshot app->Recents transition
- public static final boolean EnableScreenshotAppTransition = false;
// Enables debug drawing for the transition thumbnail
public static final boolean EnableTransitionThumbnailDebugMode = false;
// Enables the filtering of tasks according to their grouping
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 01ba5a2..d2c55f7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -28,6 +28,8 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.os.UserHandle;
import android.util.Pair;
import android.view.KeyEvent;
@@ -102,8 +104,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
@Override
public void run() {
// Mark Recents as no longer visible
- AlternateRecentsComponent.notifyVisibilityChanged(false);
- mVisible = false;
+ onRecentsActivityVisibilityChanged(false);
// Finish Recents
if (mLaunchIntent != null) {
if (mLaunchOpts != null) {
@@ -141,14 +142,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
} else if (action.equals(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
// If we are toggling Recents, then first unfilter any filtered stacks first
dismissRecentsToFocusedTaskOrHome(true);
- } else if (action.equals(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION)) {
- // Try and start the enter animation (or restart it on configuration changed)
- ReferenceCountedTrigger t = new ReferenceCountedTrigger(context, null, null, null);
- mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
- onEnterAnimationTriggered();
- // Notify the fallback receiver that we have successfully got the broadcast
- // See AlternateRecentsComponent.onAnimationStarted()
- setResultCode(Activity.RESULT_OK);
}
}
};
@@ -163,6 +156,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
// When the screen turns off, dismiss Recents to Home
dismissRecentsToHome(false);
+ // Start preloading some tasks in the background
+ RecentsTaskLoader.getInstance().preload(RecentsActivity.this);
} else if (action.equals(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED)) {
// When the search activity changes, update the Search widget
refreshSearchWidget();
@@ -189,8 +184,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
AlternateRecentsComponent.EXTRA_FROM_HOME, false);
mConfig.launchedFromAppWithThumbnail = launchIntent.getBooleanExtra(
AlternateRecentsComponent.EXTRA_FROM_APP_THUMBNAIL, false);
- mConfig.launchedFromAppWithScreenshot = launchIntent.getBooleanExtra(
- AlternateRecentsComponent.EXTRA_FROM_APP_FULL_SCREENSHOT, false);
mConfig.launchedToTaskId = launchIntent.getIntExtra(
AlternateRecentsComponent.EXTRA_FROM_TASK_ID, -1);
mConfig.launchedWithAltTab = launchIntent.getBooleanExtra(
@@ -435,6 +428,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
}
+ /** Called when the configuration changes. */
void onConfigurationChange() {
// Update RecentsConfiguration
mConfig = RecentsConfiguration.reinitialize(this,
@@ -443,7 +437,16 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Try and start the enter animation (or restart it on configuration changed)
ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
- onEnterAnimationTriggered();
+ // Animate the SystemUI scrim views
+ mScrimViews.startEnterRecentsAnimation();
+ }
+
+ /** Handles changes to the activity visibility. */
+ void onRecentsActivityVisibilityChanged(boolean visible) {
+ if (!visible) {
+ AlternateRecentsComponent.notifyVisibilityChanged(visible);
+ }
+ mVisible = visible;
}
@Override
@@ -471,7 +474,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
IntentFilter filter = new IntentFilter();
filter.addAction(AlternateRecentsComponent.ACTION_HIDE_RECENTS_ACTIVITY);
filter.addAction(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY);
- filter.addAction(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION);
registerReceiver(mServiceBroadcastReceiver, filter);
// Register any broadcast receivers for the task loader
@@ -483,7 +485,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
super.onResume();
// Mark Recents as visible
- mVisible = true;
+ onRecentsActivityVisibilityChanged(true);
}
@Override
@@ -514,6 +516,16 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
@Override
+ public void onEnterAnimationComplete() {
+ // Try and start the enter animation (or restart it on configuration changed)
+ ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
+ mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
+
+ // Animate the SystemUI scrim views
+ mScrimViews.startEnterRecentsAnimation();
+ }
+
+ @Override
public void onTrimMemory(int level) {
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
if (loader != null) {
@@ -594,12 +606,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
}
- /** Called when the enter recents animation is triggered. */
- public void onEnterAnimationTriggered() {
- // Animate the SystemUI scrim views
- mScrimViews.startEnterRecentsAnimation();
- }
-
/**** RecentsView.RecentsViewCallbacks Implementation ****/
@Override
@@ -611,8 +617,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
@Override
public void onTaskViewClicked() {
// Mark recents as no longer visible
- AlternateRecentsComponent.notifyVisibilityChanged(false);
- mVisible = false;
+ onRecentsActivityVisibilityChanged(false);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 2aca576..bfea3f7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -307,7 +307,6 @@ public class RecentsConfiguration {
launchedWithAltTab = false;
launchedWithNoRecentTasks = false;
launchedFromAppWithThumbnail = false;
- launchedFromAppWithScreenshot = false;
launchedFromHome = false;
launchedToTaskId = -1;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
index f01d17c..a0dee07 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
@@ -16,6 +16,7 @@
package com.android.systemui.recents.misc;
+import android.animation.Animator;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Matrix;
@@ -188,4 +189,15 @@ public class Utilities {
int flags = intent.getFlags();
return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) == Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
}
+
+ /**
+ * Cancels an animation ensuring that if it has listeners, onCancel and onEnd
+ * are not called.
+ */
+ public static void cancelAnimationWithoutCallbacks(Animator animator) {
+ if (animator != null) {
+ animator.removeAllListeners();
+ animator.cancel();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java b/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java
index 7ccefc6..97e0916 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/KeyStoreLruCache.java
@@ -21,15 +21,16 @@ import android.util.LruCache;
import java.util.HashMap;
/**
- * An LRU cache that support querying the keys as well as values. By using the Task's key, we can
- * prevent holding onto a reference to the Task resource data, while keeping the cache data in
- * memory where necessary.
+ * An LRU cache that internally support querying the keys as well as values. We use this to keep
+ * track of the task metadata to determine when to invalidate the cache when tasks have been
+ * updated. Generally, this cache will return the last known cache value for the requested task
+ * key.
*/
public class KeyStoreLruCache<V> {
// We keep a set of keys that are associated with the LRU cache, so that we can find out
// information about the Task that was previously in the cache.
HashMap<Integer, Task.TaskKey> mTaskKeys = new HashMap<Integer, Task.TaskKey>();
- // The cache implementation
+ // The cache implementation, mapping task id -> value
LruCache<Integer, V> mCache;
public KeyStoreLruCache(int cacheSize) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
index 60e89bf..e48e5f0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsPackageMonitor.java
@@ -19,6 +19,7 @@ package com.android.systemui.recents.model;
import android.content.ComponentName;
import android.content.Context;
import android.os.Looper;
+import android.os.UserHandle;
import com.android.internal.content.PackageMonitor;
import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -26,16 +27,16 @@ import java.util.HashSet;
import java.util.List;
/**
- * The package monitor listens for changes from PackageManager to update the contents of the Recents
- * list.
+ * The package monitor listens for changes from PackageManager to update the contents of the
+ * Recents list.
*/
public class RecentsPackageMonitor extends PackageMonitor {
public interface PackageCallbacks {
- public void onComponentRemoved(HashSet<ComponentName> cns);
+ public void onPackagesChanged(RecentsPackageMonitor monitor, String packageName,
+ int userId);
}
PackageCallbacks mCb;
- List<Task.TaskKey> mTasks;
SystemServicesProxy mSystemServicesProxy;
/** Registers the broadcast receivers with the specified callbacks. */
@@ -43,7 +44,9 @@ public class RecentsPackageMonitor extends PackageMonitor {
mSystemServicesProxy = new SystemServicesProxy(context);
mCb = cb;
try {
- register(context, Looper.getMainLooper(), true);
+ // We register for events from all users, but will cross-reference them with
+ // packages for the current user and any profiles they have
+ register(context, Looper.getMainLooper(), UserHandle.ALL, true);
} catch (IllegalStateException e) {
e.printStackTrace();
}
@@ -59,29 +62,15 @@ public class RecentsPackageMonitor extends PackageMonitor {
}
mSystemServicesProxy = null;
mCb = null;
- mTasks.clear();
- }
-
- /** Sets the list of tasks to match against package broadcast changes. */
- void setTasks(List<Task.TaskKey> tasks) {
- mTasks = tasks;
}
@Override
public void onPackageRemoved(String packageName, int uid) {
if (mCb == null) return;
- // Identify all the tasks that should be removed as a result of the package being removed.
- // Using a set to ensure that we callback once per unique component.
- HashSet<ComponentName> componentsToRemove = new HashSet<ComponentName>();
- for (Task.TaskKey t : mTasks) {
- ComponentName cn = t.baseIntent.getComponent();
- if (cn.getPackageName().equals(packageName)) {
- componentsToRemove.add(cn);
- }
- }
- // Notify our callbacks that the components no longer exist
- mCb.onComponentRemoved(componentsToRemove);
+ // Notify callbacks that a package has changed
+ final int eventUserId = getChangingUserId();
+ mCb.onPackagesChanged(this, packageName, eventUserId);
}
@Override
@@ -94,25 +83,38 @@ public class RecentsPackageMonitor extends PackageMonitor {
public void onPackageModified(String packageName) {
if (mCb == null) return;
+ // Notify callbacks that a package has changed
+ final int eventUserId = getChangingUserId();
+ mCb.onPackagesChanged(this, packageName, eventUserId);
+ }
+
+ /**
+ * Computes the components that have been removed as a result of a change in the specified
+ * package.
+ */
+ public HashSet<ComponentName> computeComponentsRemoved(List<Task.TaskKey> taskKeys,
+ String packageName, int userId) {
// Identify all the tasks that should be removed as a result of the package being removed.
// Using a set to ensure that we callback once per unique component.
- HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>();
- HashSet<ComponentName> componentsToRemove = new HashSet<ComponentName>();
- for (Task.TaskKey t : mTasks) {
+ HashSet<ComponentName> existingComponents = new HashSet<ComponentName>();
+ HashSet<ComponentName> removedComponents = new HashSet<ComponentName>();
+ for (Task.TaskKey t : taskKeys) {
+ // Skip if this doesn't apply to the current user
+ if (t.userId != userId) continue;
+
ComponentName cn = t.baseIntent.getComponent();
if (cn.getPackageName().equals(packageName)) {
- if (componentsKnownToExist.contains(cn)) {
+ if (existingComponents.contains(cn)) {
// If we know that the component still exists in the package, then skip
continue;
}
- if (mSystemServicesProxy.getActivityInfo(cn) != null) {
- componentsKnownToExist.add(cn);
+ if (mSystemServicesProxy.getActivityInfo(cn, userId) != null) {
+ existingComponents.add(cn);
} else {
- componentsToRemove.add(cn);
+ removedComponents.add(cn);
}
}
}
- // Notify our callbacks that the components no longer exist
- mCb.onComponentRemoved(componentsToRemove);
+ return removedComponents;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index d40e847..b4f62d5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -171,6 +171,9 @@ class TaskResourceLoader implements Runnable {
}
} else {
SystemServicesProxy ssp = mSystemServicesProxy;
+ // If we've stopped the loader, then fall thorugh to the above logic to wait on
+ // the load thread
+ if (ssp == null) continue;
// Load the next item from the queue
final Task t = mLoadQueue.nextTask();
@@ -418,17 +421,25 @@ public class RecentsTaskLoader {
root.setStack(stack);
// Start the task loader and add all the tasks we need to load
- mLoader.start(context);
mLoadQueue.addTasks(tasksToLoad);
-
- // Update the package monitor with the list of packages to listen for
- mPackageMonitor.setTasks(taskKeys);
+ mLoader.start(context);
return root;
}
+ /** Preloads the set of recent tasks (not including thumbnails). */
+ public void preload(Context context) {
+ ArrayList<Task> tasksToLoad = new ArrayList<Task>();
+ getTaskStack(mSystemServicesProxy, context.getResources(),
+ -1, -1, true, true, null, tasksToLoad);
+
+ // Start the task loader and add all the tasks we need to load
+ mLoadQueue.addTasks(tasksToLoad);
+ mLoader.start(context);
+ }
+
/** Creates a lightweight stack of the current recent tasks, without thumbnails and icons. */
- public TaskStack getTaskStack(SystemServicesProxy ssp, Resources res,
+ public synchronized TaskStack getTaskStack(SystemServicesProxy ssp, Resources res,
int preloadTaskId, int preloadTaskCount,
boolean loadTaskThumbnails, boolean isTopTaskHome,
List<Task.TaskKey> taskKeysOut, List<Task> tasksToLoadOut) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index a7e2b0b..55dfe45 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -129,7 +129,7 @@ public class Task {
TaskCallbacks mCb;
public Task() {
- // Only used by RecentsService for task rect calculations.
+ // Do nothing
}
public Task(TaskKey key, boolean isActive, int taskAffiliation, int taskAffiliationColor,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 1e47b50..a37b9e6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -255,6 +255,17 @@ public class TaskStack {
return mTaskList.getTasks().get(mTaskList.size() - 1);
}
+ /** Gets the task keys */
+ public ArrayList<Task.TaskKey> getTaskKeys() {
+ ArrayList<Task.TaskKey> taskKeys = new ArrayList<Task.TaskKey>();
+ ArrayList<Task> tasks = mTaskList.getTasks();
+ int taskCount = tasks.size();
+ for (int i = 0; i < taskCount; i++) {
+ taskKeys.add(tasks.get(i).key);
+ }
+ return taskKeys;
+ }
+
/** Gets the tasks */
public ArrayList<Task> getTasks() {
return mTaskList.getTasks();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
index d2fdaff..5f8f3f2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
@@ -17,12 +17,10 @@
package com.android.systemui.recents.views;
import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
import android.graphics.Outline;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewOutlineProvider;
-
import com.android.systemui.recents.RecentsConfiguration;
/* An outline provider that has a clip and outline that can be animated. */
@@ -31,35 +29,27 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
RecentsConfiguration mConfig;
TaskView mSourceView;
- Rect mTmpRect = new Rect();
Rect mClipRect = new Rect();
Rect mClipBounds = new Rect();
- Rect mOutlineClipRect = new Rect();
int mCornerRadius;
float mAlpha = 1f;
final float mMinAlpha = 0.25f;
- ObjectAnimator mClipTopAnimator;
- ObjectAnimator mClipRightAnimator;
ObjectAnimator mClipBottomAnimator;
public AnimateableViewBounds(TaskView source, int cornerRadius) {
mConfig = RecentsConfiguration.getInstance();
mSourceView = source;
mCornerRadius = cornerRadius;
- setClipTop(getClipTop());
- setClipRight(getClipRight());
setClipBottom(getClipBottom());
- setOutlineClipBottom(getOutlineClipBottom());
}
@Override
public void getOutline(View view, Outline outline) {
outline.setAlpha(mMinAlpha + mAlpha / (1f - mMinAlpha));
- outline.setRoundRect(Math.max(mClipRect.left, mOutlineClipRect.left),
- Math.max(mClipRect.top, mOutlineClipRect.top),
- mSourceView.getWidth() - Math.max(mClipRect.right, mOutlineClipRect.right),
- mSourceView.getHeight() - Math.max(mClipRect.bottom, mOutlineClipRect.bottom),
+ outline.setRoundRect(mClipRect.left, mClipRect.top,
+ mSourceView.getWidth() - mClipRect.right,
+ mSourceView.getHeight() - mClipRect.bottom,
mCornerRadius);
}
@@ -71,73 +61,6 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
}
}
- /** Animates the top clip. */
- void animateClipTop(int top, int duration, ValueAnimator.AnimatorUpdateListener updateListener) {
- if (mClipTopAnimator != null) {
- mClipTopAnimator.removeAllListeners();
- mClipTopAnimator.cancel();
- }
- mClipTopAnimator = ObjectAnimator.ofInt(this, "clipTop", top);
- mClipTopAnimator.setDuration(duration);
- mClipTopAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
- if (updateListener != null) {
- mClipTopAnimator.addUpdateListener(updateListener);
- }
- mClipTopAnimator.start();
- }
-
- /** Sets the top clip. */
- public void setClipTop(int top) {
- if (top != mClipRect.top) {
- mClipRect.top = top;
- mSourceView.invalidateOutline();
- updateClipBounds();
- }
- }
-
- /** Returns the top clip. */
- public int getClipTop() {
- return mClipRect.top;
- }
-
- /** Animates the right clip. */
- void animateClipRight(int right, int duration) {
- if (mClipRightAnimator != null) {
- mClipRightAnimator.removeAllListeners();
- mClipRightAnimator.cancel();
- }
- mClipRightAnimator = ObjectAnimator.ofInt(this, "clipRight", right);
- mClipRightAnimator.setDuration(duration);
- mClipRightAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
- mClipRightAnimator.start();
- }
-
- /** Sets the right clip. */
- public void setClipRight(int right) {
- if (right != mClipRect.right) {
- mClipRect.right = right;
- mSourceView.invalidateOutline();
- updateClipBounds();
- }
- }
-
- /** Returns the right clip. */
- public int getClipRight() {
- return mClipRect.right;
- }
-
- /** Animates the bottom clip. */
- void animateClipBottom(int bottom, int duration) {
- if (mClipBottomAnimator != null) {
- mClipBottomAnimator.removeAllListeners();
- mClipBottomAnimator.cancel();
- }
- mClipBottomAnimator = ObjectAnimator.ofInt(this, "clipBottom", bottom);
- mClipBottomAnimator.setDuration(duration);
- mClipBottomAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
- mClipBottomAnimator.start();
- }
-
/** Sets the bottom clip. */
public void setClipBottom(int bottom) {
if (bottom != mClipRect.bottom) {
@@ -145,7 +68,7 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
mSourceView.invalidateOutline();
updateClipBounds();
if (!mConfig.useHardwareLayers) {
- mSourceView.mThumbnailView.updateVisibility(
+ mSourceView.mThumbnailView.updateThumbnailVisibility(
bottom - mSourceView.getPaddingBottom());
}
}
@@ -156,19 +79,6 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
return mClipRect.bottom;
}
- /** Sets the outline bottom clip. */
- public void setOutlineClipBottom(int bottom) {
- if (bottom != mOutlineClipRect.bottom) {
- mOutlineClipRect.bottom = bottom;
- mSourceView.invalidateOutline();
- }
- }
-
- /** Gets the outline bottom clip. */
- public int getOutlineClipBottom() {
- return mOutlineClipRect.bottom;
- }
-
private void updateClipBounds() {
mClipBounds.set(mClipRect.left, mClipRect.top,
mSourceView.getWidth() - mClipRect.right,
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 6c22a3b..6b0d306 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -18,8 +18,6 @@ package com.android.systemui.recents.views;
import android.app.ActivityOptions;
import android.app.TaskStackBuilder;
-import android.content.ActivityNotFoundException;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
@@ -35,7 +33,6 @@ import android.view.WindowInsets;
import android.widget.FrameLayout;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.misc.Console;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.RecentsPackageMonitor;
@@ -44,7 +41,6 @@ import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
-import java.util.HashSet;
/**
* This view is the the top level layout that contains TaskStacks (which are laid out according
@@ -339,7 +335,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
View child = getChildAt(i);
if (child != mSearchBar) {
TaskStackView stackView = (TaskStackView) child;
- stackView.focusNextTask(forward);
+ stackView.focusNextTask(forward, true);
break;
}
}
@@ -566,14 +562,14 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
/**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
@Override
- public void onComponentRemoved(HashSet<ComponentName> cns) {
+ public void onPackagesChanged(RecentsPackageMonitor monitor, String packageName, int userId) {
// Propagate this event down to each task stack view
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child != mSearchBar) {
TaskStackView stackView = (TaskStackView) child;
- stackView.onComponentRemoved(cns);
+ stackView.onPackagesChanged(monitor, packageName, userId);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 40134da..dee26e6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -24,7 +24,6 @@ import android.graphics.Rect;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
import com.android.systemui.R;
@@ -415,7 +414,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
/** Focuses the task at the specified index in the stack */
- void focusTask(int taskIndex, boolean scrollToNewPosition) {
+ void focusTask(int taskIndex, boolean scrollToNewPosition, final boolean animateFocusedState) {
// Return early if the task is already focused
if (taskIndex == mFocusedTaskIndex) return;
@@ -427,7 +426,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
TaskView tv = getChildViewForTask(t);
Runnable postScrollRunnable = null;
if (tv != null) {
- tv.setFocusedTask();
+ tv.setFocusedTask(animateFocusedState);
} else {
postScrollRunnable = new Runnable() {
@Override
@@ -435,7 +434,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
Task t = mStack.getTasks().get(mFocusedTaskIndex);
TaskView tv = getChildViewForTask(t);
if (tv != null) {
- tv.setFocusedTask();
+ tv.setFocusedTask(animateFocusedState);
}
}
};
@@ -455,18 +454,50 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
- /** Focuses the next task in the stack */
- void focusNextTask(boolean forward) {
+ /**
+ * Ensures that there is a task focused, if nothign is focused, then we will use the task
+ * at the center of the visible stack.
+ */
+ public boolean ensureFocusedTask() {
+ if (mFocusedTaskIndex < 0) {
+ // If there is no task focused, then find the task that is closes to the center
+ // of the screen and use that as the currently focused task
+ int x = mLayoutAlgorithm.mStackVisibleRect.centerX();
+ int y = mLayoutAlgorithm.mStackVisibleRect.centerY();
+ int childCount = getChildCount();
+ for (int i = childCount - 1; i >= 0; i--) {
+ TaskView tv = (TaskView) getChildAt(i);
+ tv.getHitRect(mTmpRect);
+ if (mTmpRect.contains(x, y)) {
+ mFocusedTaskIndex = mStack.indexOfTask(tv.getTask());
+ break;
+ }
+ }
+ // If we can't find the center task, then use the front most index
+ if (mFocusedTaskIndex < 0 && childCount > 0) {
+ mFocusedTaskIndex = childCount - 1;
+ }
+ }
+ return mFocusedTaskIndex >= 0;
+ }
+
+ /**
+ * Focuses the next task in the stack.
+ * @param animateFocusedState determines whether to actually draw the highlight along with
+ * the change in focus, as well as whether to scroll to fit the
+ * task into view.
+ */
+ public void focusNextTask(boolean forward, boolean animateFocusedState) {
// Find the next index to focus
int numTasks = mStack.getTaskCount();
if (numTasks == 0) return;
- int nextFocusIndex = numTasks - 1;
- if (0 <= mFocusedTaskIndex && mFocusedTaskIndex < numTasks) {
- nextFocusIndex = Math.max(0, Math.min(numTasks - 1,
- mFocusedTaskIndex + (forward ? -1 : 1)));
+ int direction = (forward ? -1 : 1);
+ int newIndex = mFocusedTaskIndex + direction;
+ if (newIndex >= 0 && newIndex <= (numTasks - 1)) {
+ newIndex = Math.max(0, Math.min(numTasks - 1, newIndex));
+ focusTask(newIndex, true, animateFocusedState);
}
- focusTask(nextFocusIndex, true);
}
/** Dismisses the focused task. */
@@ -506,6 +537,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
@Override
+ public boolean onGenericMotionEvent(MotionEvent ev) {
+ return mTouchHandler.onGenericMotionEvent(ev);
+ }
+
+ @Override
public void computeScroll() {
mStackScroller.computeScroll();
// Synchronize the views
@@ -562,22 +598,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
TaskView tv = (TaskView) getChildAt(i);
- if (tv.isFullScreenView()) {
- tv.measure(widthMeasureSpec, heightMeasureSpec);
+ if (tv.getBackground() != null) {
+ tv.getBackground().getPadding(mTmpRect);
} else {
- if (tv.getBackground() != null) {
- tv.getBackground().getPadding(mTmpRect);
- } else {
- mTmpRect.setEmpty();
- }
- tv.measure(
- MeasureSpec.makeMeasureSpec(
- mLayoutAlgorithm.mTaskRect.width() + mTmpRect.left + mTmpRect.right,
- MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(
- mLayoutAlgorithm.mTaskRect.height() + mTmpRect.top + mTmpRect.bottom +
- tv.getMaxFooterHeight(), MeasureSpec.EXACTLY));
+ mTmpRect.setEmpty();
}
+ tv.measure(
+ MeasureSpec.makeMeasureSpec(
+ mLayoutAlgorithm.mTaskRect.width() + mTmpRect.left + mTmpRect.right,
+ MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(
+ mLayoutAlgorithm.mTaskRect.height() + mTmpRect.top + mTmpRect.bottom,
+ MeasureSpec.EXACTLY));
}
setMeasuredDimension(width, height);
@@ -594,20 +626,15 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
TaskView tv = (TaskView) getChildAt(i);
- if (tv.isFullScreenView()) {
- tv.layout(left, top, left + tv.getMeasuredWidth(), top + tv.getMeasuredHeight());
+ if (tv.getBackground() != null) {
+ tv.getBackground().getPadding(mTmpRect);
} else {
- if (tv.getBackground() != null) {
- tv.getBackground().getPadding(mTmpRect);
- } else {
- mTmpRect.setEmpty();
- }
- tv.layout(mLayoutAlgorithm.mTaskRect.left - mTmpRect.left,
- mLayoutAlgorithm.mTaskRect.top - mTmpRect.top,
- mLayoutAlgorithm.mTaskRect.right + mTmpRect.right,
- mLayoutAlgorithm.mTaskRect.bottom + mTmpRect.bottom +
- tv.getMaxFooterHeight());
+ mTmpRect.setEmpty();
}
+ tv.layout(mLayoutAlgorithm.mTaskRect.left - mTmpRect.left,
+ mLayoutAlgorithm.mTaskRect.top - mTmpRect.top,
+ mLayoutAlgorithm.mTaskRect.right + mTmpRect.right,
+ mLayoutAlgorithm.mTaskRect.bottom + mTmpRect.bottom);
}
if (mAwaitingFirstLayout) {
@@ -653,9 +680,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// When Alt-Tabbing, we scroll to and focus the previous task
if (mConfig.launchedWithAltTab) {
if (mConfig.launchedFromHome) {
- focusTask(Math.max(0, mStack.getTaskCount() - 1), false);
+ focusTask(Math.max(0, mStack.getTaskCount() - 1), false, true);
} else {
- focusTask(Math.max(0, mStack.getTaskCount() - 2), false);
+ focusTask(Math.max(0, mStack.getTaskCount() - 2), false, true);
}
}
}
@@ -811,6 +838,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
TaskView frontTv = getChildViewForTask(newFrontMostTask);
if (frontTv != null) {
frontTv.onTaskBound(newFrontMostTask);
+ frontTv.fadeInActionButton(false);
}
}
@@ -923,13 +951,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Rebind the task and request that this task's data be filled into the TaskView
tv.onTaskBound(task);
- // Mark the launch task as fullscreen
- if (Constants.DebugFlags.App.EnableScreenshotAppTransition && mAwaitingFirstLayout) {
- if (task.isLaunchTarget) {
- tv.setIsFullScreen(true);
- }
- }
-
// Load the task data
RecentsTaskLoader.getInstance().loadTaskData(task);
@@ -1018,14 +1039,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
tv.getTask().activityLabel));
// Remove the task from the view
mStack.removeTask(task);
- // If the dismissed task was focused, then we should focus the next task in front
+ // If the dismissed task was focused, then we should focus the new task in the same index
if (taskWasFocused) {
ArrayList<Task> tasks = mStack.getTasks();
- int nextTaskIndex = Math.min(tasks.size() - 1, taskIndex);
+ int nextTaskIndex = Math.min(tasks.size() - 1, taskIndex - 1);
if (nextTaskIndex >= 0) {
Task nextTask = tasks.get(nextTaskIndex);
TaskView nextTv = getChildViewForTask(nextTask);
- nextTv.setFocusedTask();
+ if (nextTv != null) {
+ // Focus the next task, and only animate the visible state if we are launched
+ // from Alt-Tab
+ nextTv.setFocusedTask(mConfig.launchedWithAltTab);
+ }
}
}
}
@@ -1038,11 +1063,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
@Override
- public void onTaskViewFullScreenTransitionCompleted() {
- requestSynchronizeStackViewsWithModel();
- }
-
- @Override
public void onTaskViewFocusChanged(TaskView tv, boolean focused) {
if (focused) {
mFocusedTaskIndex = mStack.indexOfTask(tv.getTask());
@@ -1061,12 +1081,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
@Override
- public void onComponentRemoved(HashSet<ComponentName> cns) {
+ public void onPackagesChanged(RecentsPackageMonitor monitor, String packageName, int userId) {
+ // Compute which components need to be removed
+ HashSet<ComponentName> removedComponents = monitor.computeComponentsRemoved(
+ mStack.getTaskKeys(), packageName, userId);
+
// For other tasks, just remove them directly if they no longer exist
ArrayList<Task> tasks = mStack.getTasks();
for (int i = tasks.size() - 1; i >= 0; i--) {
final Task t = tasks.get(i);
- if (cns.contains(t.key.baseIntent.getComponent())) {
+ if (removedComponents.contains(t.key.baseIntent.getComponent())) {
TaskView tv = getChildViewForTask(t);
if (tv != null) {
// For visible children, defer removing the task until after the animation
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
index 31fc701..c549d2b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
@@ -199,18 +199,14 @@ public class TaskStackViewLayoutAlgorithm {
return transformOut;
}
- /**
- * Returns the untransformed task view size.
- */
+ /** Returns the untransformed task view size. */
public Rect getUntransformedTaskViewSize() {
Rect tvSize = new Rect(mTaskRect);
tvSize.offsetTo(0, 0);
return tvSize;
}
- /**
- * Returns the scroll to such task top = 1f;
- */
+ /** Returns the scroll to such task top = 1f; */
float getStackScrollForTask(Task t) {
return mTaskProgressMap.get(t.key);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index 5852b88..04f7c6f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -23,6 +23,7 @@ import android.animation.ValueAnimator;
import android.content.Context;
import android.widget.OverScroller;
import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.misc.Utilities;
/* The scrolling logic for a TaskStackView */
public class TaskStackViewScroller {
@@ -38,6 +39,7 @@ public class TaskStackViewScroller {
OverScroller mScroller;
ObjectAnimator mScrollAnimator;
+ float mFinalAnimatedScroll;
public TaskStackViewScroller(Context context, RecentsConfiguration config, TaskStackViewLayoutAlgorithm layoutAlgorithm) {
mConfig = config;
@@ -128,10 +130,15 @@ public class TaskStackViewScroller {
/** Animates the stack scroll */
void animateScroll(float curScroll, float newScroll, final Runnable postRunnable) {
- // Abort any current animations
+ // Finish any current scrolling animations
+ if (mScrollAnimator != null && mScrollAnimator.isRunning()) {
+ setStackScroll(mFinalAnimatedScroll);
+ mScroller.startScroll(0, progressToScrollRange(mFinalAnimatedScroll), 0, 0, 0);
+ }
stopScroller();
stopBoundScrollAnimation();
+ mFinalAnimatedScroll = newScroll;
mScrollAnimator = ObjectAnimator.ofFloat(this, "stackScroll", curScroll, newScroll);
mScrollAnimator.setDuration(mConfig.taskStackScrollDuration);
mScrollAnimator.setInterpolator(mConfig.linearOutSlowInInterpolator);
@@ -155,10 +162,7 @@ public class TaskStackViewScroller {
/** Aborts any current stack scrolls */
void stopBoundScrollAnimation() {
- if (mScrollAnimator != null) {
- mScrollAnimator.removeAllListeners();
- mScrollAnimator.cancel();
- }
+ Utilities.cancelAnimationWithoutCallbacks(mScrollAnimator);
}
/**** OverScroller ****/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 8f9b4c2..2b173a9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -17,6 +17,7 @@
package com.android.systemui.recents.views;
import android.content.Context;
+import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
@@ -189,7 +190,6 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
/** Handles touch events once we have intercepted them */
public boolean onTouchEvent(MotionEvent ev) {
-
// Short circuit if we have no children
boolean hasChildren = (mSv.getChildCount() > 0);
if (!hasChildren) {
@@ -336,6 +336,30 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
return true;
}
+ /** Handles generic motion events */
+ public boolean onGenericMotionEvent(MotionEvent ev) {
+ if ((ev.getSource() & InputDevice.SOURCE_CLASS_POINTER) ==
+ InputDevice.SOURCE_CLASS_POINTER) {
+ int action = ev.getAction();
+ switch (action & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_SCROLL:
+ // Find the front most task and scroll the next task to the front
+ float vScroll = ev.getAxisValue(MotionEvent.AXIS_VSCROLL);
+ if (vScroll > 0) {
+ if (mSv.ensureFocusedTask()) {
+ mSv.focusNextTask(true, false);
+ }
+ } else {
+ if (mSv.ensureFocusedTask()) {
+ mSv.focusNextTask(false, false);
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
/**** SwipeHelper Implementation ****/
@Override
@@ -355,8 +379,6 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
tv.setClipViewInStack(false);
// Disallow touch events from this task view
tv.setTouchEnabled(false);
- // Hide the footer
- tv.animateFooterVisibility(false, mSv.mConfig.taskViewLockToAppShortAnimDuration);
// Disallow parents from intercepting touch events
final ViewParent parent = mSv.getParent();
if (parent != null) {
@@ -387,8 +409,6 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
tv.setClipViewInStack(true);
// Re-enable touch events from this task view
tv.setTouchEnabled(true);
- // Restore the footer
- tv.animateFooterVisibility(true, mSv.mConfig.taskViewLockToAppShortAnimDuration);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 2658176..7b4e10a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -21,23 +21,22 @@ import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.*;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewOutlineProvider;
+import android.view.ViewPropertyAnimator;
import android.view.animation.AccelerateInterpolator;
import android.widget.FrameLayout;
import com.android.systemui.R;
-import com.android.systemui.recents.AlternateRecentsComponent;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.model.RecentsTaskLoader;
+import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
/* A task view */
public class TaskView extends FrameLayout implements Task.TaskCallbacks,
- TaskViewFooter.TaskFooterViewCallbacks, View.OnClickListener, View.OnLongClickListener {
+ View.OnClickListener, View.OnLongClickListener {
/** The TaskView callbacks */
interface TaskViewCallbacks {
@@ -46,7 +45,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
public void onTaskViewClicked(TaskView tv, Task task, boolean lockToTask);
public void onTaskViewDismissed(TaskView tv);
public void onTaskViewClipStateChanged(TaskView tv);
- public void onTaskViewFullScreenTransitionCompleted();
public void onTaskViewFocusChanged(TaskView tv, boolean focused);
}
@@ -54,25 +52,22 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
float mTaskProgress;
ObjectAnimator mTaskProgressAnimator;
- ObjectAnimator mDimAnimator;
float mMaxDimScale;
- int mDim;
+ int mDimAlpha;
AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator(1f);
- PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.MULTIPLY);
+ PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP);
+ Paint mDimLayerPaint = new Paint();
Task mTask;
boolean mTaskDataLoaded;
boolean mIsFocused;
boolean mFocusAnimationsEnabled;
- boolean mIsFullScreenView;
boolean mClipViewInStack;
AnimateableViewBounds mViewBounds;
- Paint mLayerPaint = new Paint();
View mContent;
TaskViewThumbnail mThumbnailView;
TaskViewHeader mHeaderView;
- TaskViewFooter mFooterView;
View mActionButtonView;
TaskViewCallbacks mCb;
@@ -133,7 +128,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mContent = findViewById(R.id.task_view_content);
mHeaderView = (TaskViewHeader) findViewById(R.id.task_view_bar);
mThumbnailView = (TaskViewThumbnail) findViewById(R.id.task_view_thumbnail);
- mThumbnailView.enableTaskBarClip(mHeaderView);
+ mThumbnailView.updateClipToTaskBar(mHeaderView);
mActionButtonView = findViewById(R.id.lock_to_app_fab);
mActionButtonView.setOutlineProvider(new ViewOutlineProvider() {
@Override
@@ -142,9 +137,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
outline.setOval(0, 0, mActionButtonView.getWidth(), mActionButtonView.getHeight());
}
});
- if (mFooterView != null) {
- mFooterView.setCallbacks(this);
- }
}
@Override
@@ -159,29 +151,16 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mContent.measure(MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY));
- // Measure the bar view, thumbnail, and footer
+ // Measure the bar view, and action button
mHeaderView.measure(MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mConfig.taskBarHeight, MeasureSpec.EXACTLY));
- if (mFooterView != null) {
- mFooterView.measure(
- MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(mConfig.taskViewLockToAppButtonHeight,
- MeasureSpec.EXACTLY));
- }
mActionButtonView.measure(
MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(heightWithoutPadding, MeasureSpec.AT_MOST));
- if (mIsFullScreenView) {
- // Measure the thumbnail height to be the full dimensions
- mThumbnailView.measure(
- MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(heightWithoutPadding, MeasureSpec.EXACTLY));
- } else {
- // Measure the thumbnail to be square
- mThumbnailView.measure(
- MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY));
- }
+ // Measure the thumbnail to be square
+ mThumbnailView.measure(
+ MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY));
setMeasuredDimension(width, height);
invalidateOutline();
}
@@ -193,25 +172,12 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform, int duration,
ValueAnimator.AnimatorUpdateListener updateCallback) {
- // If we are a full screen view, then only update the Z to keep it in order
- // XXX: Also update/animate the dim as well
- if (mIsFullScreenView) {
- if (!mConfig.fakeShadows &&
- toTransform.hasTranslationZChangedFrom(getTranslationZ())) {
- setTranslationZ(toTransform.translationZ);
- }
- return;
- }
-
// Apply the transform
toTransform.applyToTaskView(this, duration, mConfig.fastOutSlowInInterpolator, false,
!mConfig.fakeShadows, updateCallback);
// Update the task progress
- if (mTaskProgressAnimator != null) {
- mTaskProgressAnimator.removeAllListeners();
- mTaskProgressAnimator.cancel();
- }
+ Utilities.cancelAnimationWithoutCallbacks(mTaskProgressAnimator);
if (duration <= 0) {
setTaskProgress(toTransform.p);
} else {
@@ -253,22 +219,12 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask,
boolean occludesLaunchTarget, int offscreenY) {
int initialDim = getDim();
- if (mConfig.launchedFromAppWithScreenshot) {
+ if (mConfig.launchedFromAppWithThumbnail) {
if (isTaskViewLaunchTargetTask) {
- // Hide the footer during the transition in, and animate it out afterwards?
- if (mFooterView != null) {
- mFooterView.animateFooterVisibility(false, 0);
- }
- } else {
- // Don't do anything for the side views when animating in
- }
-
- } else if (mConfig.launchedFromAppWithThumbnail) {
- if (isTaskViewLaunchTargetTask) {
- // Hide the action button if it exists
- mActionButtonView.setAlpha(0f);
// Set the dim to 0 so we can animate it in
initialDim = 0;
+ // Hide the action button
+ mActionButtonView.setAlpha(0f);
} else if (occludesLaunchTarget) {
// Move the task view off screen (below) so we can animate it in
setTranslationY(offscreenY);
@@ -292,74 +248,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
final TaskViewTransform transform = ctx.currentTaskTransform;
int startDelay = 0;
- if (mConfig.launchedFromAppWithScreenshot) {
- if (mTask.isLaunchTarget) {
- Rect taskRect = ctx.currentTaskRect;
- int duration = mConfig.taskViewEnterFromHomeDuration * 10;
- int windowInsetTop = mConfig.systemInsets.top; // XXX: Should be for the window
- float taskScale = ((float) taskRect.width() / getMeasuredWidth()) * transform.scale;
- float scaledYOffset = ((1f - taskScale) * getMeasuredHeight()) / 2;
- float scaledWindowInsetTop = (int) (taskScale * windowInsetTop);
- float scaledTranslationY = taskRect.top + transform.translationY -
- (scaledWindowInsetTop + scaledYOffset);
- startDelay = mConfig.taskViewEnterFromHomeStaggerDelay;
-
- // Animate the top clip
- mViewBounds.animateClipTop(windowInsetTop, duration,
- new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- int y = (Integer) animation.getAnimatedValue();
- mHeaderView.setTranslationY(y);
- }
- });
- // Animate the bottom or right clip
- int size = Math.round((taskRect.width() / taskScale));
- if (mConfig.hasHorizontalLayout()) {
- mViewBounds.animateClipRight(getMeasuredWidth() - size, duration);
- } else {
- mViewBounds.animateClipBottom(getMeasuredHeight() - (windowInsetTop + size), duration);
- }
- // Animate the task bar of the first task view
- animate()
- .scaleX(taskScale)
- .scaleY(taskScale)
- .translationY(scaledTranslationY)
- .setDuration(duration)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- setIsFullScreen(false);
- requestLayout();
-
- // Reset the clip
- mViewBounds.setClipTop(0);
- mViewBounds.setClipBottom(0);
- mViewBounds.setClipRight(0);
- // Reset the bar translation
- mHeaderView.setTranslationY(0);
- // Animate the footer into view (if it is the front most task)
- animateFooterVisibility(true, mConfig.taskBarEnterAnimDuration);
-
- // Unbind the thumbnail from the screenshot
- RecentsTaskLoader.getInstance().loadTaskData(mTask);
- // Recycle the full screen screenshot
- AlternateRecentsComponent.consumeLastScreenshot();
-
- mCb.onTaskViewFullScreenTransitionCompleted();
-
- // Decrement the post animation trigger
- ctx.postAnimationTrigger.decrement();
- }
- })
- .start();
- } else {
- // Animate the footer into view
- animateFooterVisibility(true, 0);
- }
- ctx.postAnimationTrigger.increment();
-
- } else if (mConfig.launchedFromAppWithThumbnail) {
+ if (mConfig.launchedFromAppWithThumbnail) {
if (mTask.isLaunchTarget) {
// Animate the dim/overlay
if (Constants.DebugFlags.App.EnableThumbnailAlphaOnFrontmost) {
@@ -381,16 +270,8 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
}
ctx.postAnimationTrigger.increment();
- // Animate the footer into view
- animateFooterVisibility(true, mConfig.taskBarEnterAnimDuration);
-
// Animate the action button in
- mActionButtonView.animate().alpha(1f)
- .setStartDelay(mConfig.taskBarEnterAnimDelay)
- .setDuration(mConfig.taskBarEnterAnimDuration)
- .setInterpolator(mConfig.fastOutLinearInInterpolator)
- .withLayer()
- .start();
+ fadeInActionButton(true);
} else {
// Animate the task up if it was occluding the launch target
if (ctx.currentTaskOccludesLaunchTarget) {
@@ -442,14 +323,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
})
.start();
ctx.postAnimationTrigger.increment();
-
- // Animate the footer into view
- animateFooterVisibility(true, mConfig.taskViewEnterFromHomeDuration);
startDelay = delay;
-
- } else {
- // Animate the footer into view
- animateFooterVisibility(true, 0);
}
// Enable the focus animations from this point onwards so that they aren't affected by the
@@ -462,6 +336,21 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
}, (startDelay / 2));
}
+ public void fadeInActionButton(boolean withDelay) {
+ // Hide the action button
+ mActionButtonView.setAlpha(0f);
+
+ // Animate the action button in
+ ViewPropertyAnimator animator = mActionButtonView.animate().alpha(1f)
+ .setDuration(mConfig.taskBarEnterAnimDuration)
+ .setInterpolator(PhoneStatusBar.ALPHA_IN)
+ .withLayer();
+ if (withDelay) {
+ animator.setStartDelay(mConfig.taskBarEnterAnimDelay);
+ }
+ animator.start();
+ }
+
/** Animates this task view as it leaves recents by pressing home. */
void startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx) {
animate()
@@ -483,7 +372,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mThumbnailView.startLaunchTaskAnimation(postAnimRunnable);
// Animate the dim
- if (mDim > 0) {
+ if (mDimAlpha > 0) {
ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", 0);
anim.setDuration(mConfig.taskBarExitAnimDuration);
anim.setInterpolator(mConfig.fastOutLinearInInterpolator);
@@ -569,23 +458,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mCb.onTaskViewDismissed(tv);
}
});
- // Hide the footer
- animateFooterVisibility(false, mConfig.taskViewRemoveAnimDuration);
- }
-
- /** Sets whether this task view is full screen or not. */
- void setIsFullScreen(boolean isFullscreen) {
- mIsFullScreenView = isFullscreen;
- mHeaderView.setIsFullscreen(isFullscreen);
- if (isFullscreen) {
- // If we are full screen, then disable the bottom outline clip for the footer
- mViewBounds.setOutlineClipBottom(0);
- }
- }
-
- /** Returns whether this task view should currently be drawn as a full screen view. */
- boolean isFullScreenView() {
- return mIsFullScreenView;
}
/**
@@ -593,7 +465,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
* view.
*/
boolean shouldClipViewInStack() {
- return mClipViewInStack && !mIsFullScreenView && (getVisibility() == View.VISIBLE);
+ return mClipViewInStack && (getVisibility() == View.VISIBLE);
}
/** Sets whether this view should be clipped, or clipped against. */
@@ -604,27 +476,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
}
}
- /** Gets the max footer height. */
- public int getMaxFooterHeight() {
- if (mFooterView != null) {
- return mFooterView.mMaxFooterHeight;
- } else {
- return 0;
- }
- }
-
- /** Animates the footer into and out of view. */
- void animateFooterVisibility(boolean visible, int duration) {
- // Hide the footer if we are a full screen view
- if (mIsFullScreenView) return;
- // Hide the footer if the current task can not be locked to
- if (!mTask.lockToTaskEnabled || !mTask.lockToThisTask) return;
- // Otherwise, animate the visibility
- if (mFooterView != null) {
- mFooterView.animateFooterVisibility(visible, duration);
- }
- }
-
/** Sets the current task progress. */
public void setTaskProgress(float p) {
mTaskProgress = p;
@@ -639,26 +490,16 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
/** Returns the current dim. */
public void setDim(int dim) {
- mDim = dim;
- if (mDimAnimator != null) {
- mDimAnimator.removeAllListeners();
- mDimAnimator.cancel();
- }
+ mDimAlpha = dim;
if (mConfig.useHardwareLayers) {
// Defer setting hardware layers if we have not yet measured, or there is no dim to draw
if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0) {
- if (mDimAnimator != null) {
- mDimAnimator.removeAllListeners();
- mDimAnimator.cancel();
- }
-
- int inverse = 255 - mDim;
- mDimColorFilter.setColor(Color.argb(0xFF, inverse, inverse, inverse));
- mLayerPaint.setColorFilter(mDimColorFilter);
- mContent.setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint);
+ mDimColorFilter.setColor(Color.argb(mDimAlpha, 0, 0, 0));
+ mDimLayerPaint.setColorFilter(mDimColorFilter);
+ mContent.setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint);
}
} else {
- float dimAlpha = mDim / 255.0f;
+ float dimAlpha = mDimAlpha / 255.0f;
if (mThumbnailView != null) {
mThumbnailView.setDimAlpha(dimAlpha);
}
@@ -670,7 +511,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
/** Returns the current dim. */
public int getDim() {
- return mDim;
+ return mDimAlpha;
}
/** Animates the dim to the task progress. */
@@ -706,11 +547,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
* if the view is not currently visible, or we are in touch state (where we still want to keep
* track of focus).
*/
- public void setFocusedTask() {
+ public void setFocusedTask(boolean animateFocusedState) {
mIsFocused = true;
if (mFocusAnimationsEnabled) {
// Focus the header bar
- mHeaderView.onTaskViewFocusChanged(true);
+ mHeaderView.onTaskViewFocusChanged(true, animateFocusedState);
}
// Update the thumbnail alpha with the focus
mThumbnailView.onFocusChanged(true);
@@ -732,7 +573,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mIsFocused = false;
if (mFocusAnimationsEnabled) {
// Un-focus the header bar
- mHeaderView.onTaskViewFocusChanged(false);
+ mHeaderView.onTaskViewFocusChanged(false, true);
}
// Update the thumbnail alpha with the focus
@@ -766,7 +607,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mFocusAnimationsEnabled = true;
if (mIsFocused && !wasFocusAnimationsEnabled) {
// Re-notify the header if we were focused and animations were not previously enabled
- mHeaderView.onTaskViewFocusChanged(true);
+ mHeaderView.onTaskViewFocusChanged(true, true);
}
}
@@ -776,15 +617,12 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
public void onTaskBound(Task t) {
mTask = t;
mTask.setCallbacks(this);
- if (getMeasuredWidth() == 0) {
- // If we haven't yet measured, we should just set the footer height with any animation
- animateFooterVisibility(t.lockToThisTask, 0);
- } else {
- animateFooterVisibility(t.lockToThisTask, mConfig.taskViewLockToAppLongAnimDuration);
- }
- // Hide the action button if lock to app is disabled
- if (!t.lockToTaskEnabled && mActionButtonView.getVisibility() != View.GONE) {
- mActionButtonView.setVisibility(View.GONE);
+
+ // Hide the action button if lock to app is disabled for this view
+ int lockButtonVisibility = (!t.lockToTaskEnabled || !t.lockToThisTask) ? GONE : VISIBLE;
+ if (mActionButtonView.getVisibility() != lockButtonVisibility) {
+ mActionButtonView.setVisibility(lockButtonVisibility);
+ requestLayout();
}
}
@@ -792,18 +630,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
public void onTaskDataLoaded() {
if (mThumbnailView != null && mHeaderView != null) {
// Bind each of the views to the new task data
- if (mIsFullScreenView) {
- mThumbnailView.bindToScreenshot(AlternateRecentsComponent.getLastScreenshot());
- } else {
- mThumbnailView.rebindToTask(mTask);
- }
+ mThumbnailView.rebindToTask(mTask);
mHeaderView.rebindToTask(mTask);
// Rebind any listeners
mHeaderView.mApplicationIcon.setOnClickListener(this);
mHeaderView.mDismissButton.setOnClickListener(this);
- if (mFooterView != null) {
- mFooterView.setOnClickListener(this);
- }
mActionButtonView.setOnClickListener(this);
if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) {
if (mConfig.developerOptionsEnabled) {
@@ -824,9 +655,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
// Unbind any listeners
mHeaderView.mApplicationIcon.setOnClickListener(null);
mHeaderView.mDismissButton.setOnClickListener(null);
- if (mFooterView != null) {
- mFooterView.setOnClickListener(null);
- }
mActionButtonView.setOnClickListener(null);
if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) {
mHeaderView.mApplicationIcon.setOnLongClickListener(null);
@@ -840,19 +668,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
setOnClickListener(enabled ? this : null);
}
- /**** TaskViewFooter.TaskFooterViewCallbacks ****/
-
- @Override
- public void onTaskFooterHeightChanged(int height, int maxHeight) {
- if (mIsFullScreenView) {
- // Disable the bottom outline clip when fullscreen
- mViewBounds.setOutlineClipBottom(0);
- } else {
- // Update the bottom clip in our outline provider
- mViewBounds.setOutlineClipBottom(maxHeight - height);
- }
- }
-
/**** View.OnClickListener Implementation ****/
@Override
@@ -876,8 +691,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
// Reset the translation of the action button before we animate it out
mActionButtonView.setTranslationZ(0f);
}
- mCb.onTaskViewClicked(tv, tv.getTask(),
- (v == mFooterView || v == mActionButtonView));
+ mCb.onTaskViewClicked(tv, tv.getTask(), (v == mActionButtonView));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewFooter.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewFooter.java
deleted file mode 100644
index 324169e..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewFooter.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2014 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.recents.views;
-
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.FrameLayout;
-import com.android.systemui.recents.RecentsConfiguration;
-
-
-/** The task footer view */
-public class TaskViewFooter extends FrameLayout {
-
- interface TaskFooterViewCallbacks {
- public void onTaskFooterHeightChanged(int height, int maxHeight);
- }
-
- RecentsConfiguration mConfig;
-
- TaskFooterViewCallbacks mCb;
- int mFooterHeight;
- int mMaxFooterHeight;
- ObjectAnimator mFooterAnimator;
-
- public TaskViewFooter(Context context) {
- this(context, null);
- }
-
- public TaskViewFooter(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public TaskViewFooter(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public TaskViewFooter(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- mConfig = RecentsConfiguration.getInstance();
- mMaxFooterHeight = mConfig.taskViewLockToAppButtonHeight;
- setFooterHeight(getFooterHeight());
- }
-
- /** Sets the callbacks for when the footer height changes. */
- void setCallbacks(TaskFooterViewCallbacks cb) {
- mCb = cb;
- mCb.onTaskFooterHeightChanged(mFooterHeight, mMaxFooterHeight);
- }
-
- /** Sets the footer height. */
- public void setFooterHeight(int footerHeight) {
- if (footerHeight != mFooterHeight) {
- mFooterHeight = footerHeight;
- mCb.onTaskFooterHeightChanged(footerHeight, mMaxFooterHeight);
- }
- }
-
- /** Gets the footer height. */
- public int getFooterHeight() {
- return mFooterHeight;
- }
-
- /** Animates the footer into and out of view. */
- void animateFooterVisibility(final boolean visible, int duration) {
- // Return early if there is no footer
- if (mMaxFooterHeight <= 0) return;
-
- // Cancel the previous animation
- if (mFooterAnimator != null) {
- mFooterAnimator.removeAllListeners();
- mFooterAnimator.cancel();
- }
- int finalHeight = visible ? mMaxFooterHeight : 0;
- if (duration > 0) {
- mFooterAnimator = ObjectAnimator.ofInt(this, "footerHeight", finalHeight);
- mFooterAnimator.setDuration(duration);
- mFooterAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
- mFooterAnimator.start();
- } else {
- setFooterHeight(finalHeight);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 396d441..ba868f5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -36,7 +36,6 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.RippleDrawable;
-import android.graphics.drawable.ShapeDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
@@ -56,25 +55,27 @@ public class TaskViewHeader extends FrameLayout {
RecentsConfiguration mConfig;
+ // Header views
ImageView mDismissButton;
ImageView mApplicationIcon;
TextView mActivityDescription;
- RippleDrawable mBackground;
- GradientDrawable mBackgroundColorDrawable;
+ // Header drawables
+ boolean mCurrentPrimaryColorIsDark;
+ int mCurrentPrimaryColor;
int mBackgroundColor;
Drawable mLightDismissDrawable;
Drawable mDarkDismissDrawable;
+ RippleDrawable mBackground;
+ GradientDrawable mBackgroundColorDrawable;
AnimatorSet mFocusAnimator;
- ValueAnimator backgroundColorAnimator;
- PorterDuffColorFilter mDimFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP);
-
- boolean mIsFullscreen;
- boolean mCurrentPrimaryColorIsDark;
- int mCurrentPrimaryColor;
+ // Static highlight that we draw at the top of each view
static Paint sHighlightPaint;
- private Paint mDimPaint = new Paint();
+
+ // Header dim, which is only used when task view hardware layers are not used
+ Paint mDimLayerPaint = new Paint();
+ PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP);
public TaskViewHeader(Context context) {
this(context, null);
@@ -159,21 +160,14 @@ public class TaskViewHeader extends FrameLayout {
@Override
protected void onDraw(Canvas canvas) {
- if (!mIsFullscreen) {
- // Draw the highlight at the top edge (but put the bottom edge just out of view)
- float offset = (float) Math.ceil(mConfig.taskViewHighlightPx / 2f);
- float radius = mConfig.taskViewRoundedCornerRadiusPx;
- int count = canvas.save(Canvas.CLIP_SAVE_FLAG);
- canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight());
- canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset,
- getMeasuredHeight() + radius, radius, radius, sHighlightPaint);
- canvas.restoreToCount(count);
- }
- }
-
- /** Sets whether the current task is full screen or not. */
- void setIsFullscreen(boolean isFullscreen) {
- mIsFullscreen = isFullscreen;
+ // Draw the highlight at the top edge (but put the bottom edge just out of view)
+ float offset = (float) Math.ceil(mConfig.taskViewHighlightPx / 2f);
+ float radius = mConfig.taskViewRoundedCornerRadiusPx;
+ int count = canvas.save(Canvas.CLIP_SAVE_FLAG);
+ canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight());
+ canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset,
+ getMeasuredHeight() + radius, radius, radius, sHighlightPaint);
+ canvas.restoreToCount(count);
}
@Override
@@ -181,6 +175,16 @@ public class TaskViewHeader extends FrameLayout {
return false;
}
+ /**
+ * Sets the dim alpha, only used when we are not using hardware layers.
+ * (see RecentsConfiguration.useHardwareLayers)
+ */
+ void setDimAlpha(int alpha) {
+ mDimColorFilter.setColor(Color.argb(alpha, 0, 0, 0));
+ mDimLayerPaint.setColorFilter(mDimColorFilter);
+ setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint);
+ }
+
/** Returns the secondary color for a primary color. */
int getSecondaryColor(int primaryColor, boolean useLightOverlayColor) {
int overlayColor = useLightOverlayColor ? Color.WHITE : Color.BLACK;
@@ -268,13 +272,16 @@ public class TaskViewHeader extends FrameLayout {
}
/** Notifies the associated TaskView has been focused. */
- void onTaskViewFocusChanged(boolean focused) {
+ void onTaskViewFocusChanged(boolean focused, boolean animateFocusedState) {
+ // If we are not animating the visible state, just return
+ if (!animateFocusedState) return;
+
boolean isRunning = false;
if (mFocusAnimator != null) {
isRunning = mFocusAnimator.isRunning();
- mFocusAnimator.removeAllListeners();
- mFocusAnimator.cancel();
+ Utilities.cancelAnimationWithoutCallbacks(mFocusAnimator);
}
+
if (focused) {
int secondaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
int[][] states = new int[][] {
@@ -349,11 +356,4 @@ public class TaskViewHeader extends FrameLayout {
}
}
}
-
- public void setDimAlpha(int alpha) {
- int color = Color.argb(alpha, 0, 0, 0);
- mDimFilter.setColor(color);
- mDimPaint.setColorFilter(mDimFilter);
- setLayerType(LAYER_TYPE_HARDWARE, mDimPaint);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index a946a84..c83248e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -33,37 +33,48 @@ import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;
import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
-/** The task thumbnail view */
+/**
+ * The task thumbnail view. It implements an image view that allows for animating the dim and
+ * alpha of the thumbnail image.
+ */
public class TaskViewThumbnail extends View {
- private final int mCornerRadius;
- private final Matrix mScaleMatrix = new Matrix();
RecentsConfiguration mConfig;
- // Task bar clipping
- Rect mClipRect = new Rect();
+ // Drawing
+ float mDimAlpha;
+ Matrix mScaleMatrix = new Matrix();
Paint mDrawPaint = new Paint();
+ RectF mBitmapRect = new RectF();
+ RectF mLayoutRect = new RectF();
+ BitmapShader mBitmapShader;
LightingColorFilter mLightingColorFilter = new LightingColorFilter(0xffffffff, 0);
- private final RectF mBitmapRect = new RectF();
- private final RectF mLayoutRect = new RectF();
- private BitmapShader mBitmapShader;
- private float mBitmapAlpha;
- private float mDimAlpha;
- private View mTaskBar;
- private boolean mInvisible;
- private ValueAnimator mAlphaAnimator;
- private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener
+
+ // Thumbnail alpha
+ float mThumbnailAlpha;
+ ValueAnimator mThumbnailAlphaAnimator;
+ ValueAnimator.AnimatorUpdateListener mThumbnailAlphaUpdateListener
= new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
- mBitmapAlpha = (float) animation.getAnimatedValue();
- updateFilter();
+ mThumbnailAlpha = (float) animation.getAnimatedValue();
+ updateThumbnailPaintFilter();
}
};
+ // Task bar clipping, the top of this thumbnail can be clipped against the opaque header
+ // bar that overlaps this thumbnail
+ View mTaskBar;
+ Rect mClipRect = new Rect();
+
+ // Visibility optimization, if the thumbnail height is less than the height of the header
+ // bar for the task view, then just mark this thumbnail view as invisible
+ boolean mInvisible;
+
public TaskViewThumbnail(Context context) {
this(context, null);
}
@@ -79,53 +90,82 @@ public class TaskViewThumbnail extends View {
public TaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mConfig = RecentsConfiguration.getInstance();
- mCornerRadius = mConfig.taskViewRoundedCornerRadiusPx;
mDrawPaint.setColorFilter(mLightingColorFilter);
mDrawPaint.setFilterBitmap(true);
mDrawPaint.setAntiAlias(true);
}
@Override
+ protected void onFinishInflate() {
+ mThumbnailAlpha = mConfig.taskViewThumbnailAlpha;
+ updateThumbnailPaintFilter();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ if (changed) {
+ mLayoutRect.set(0, 0, getWidth(), getHeight());
+ updateThumbnailScale();
+ }
+ }
+
+ @Override
protected void onDraw(Canvas canvas) {
if (mInvisible) {
return;
}
- canvas.drawRoundRect(0,
- 0,
- getWidth(),
- getHeight(),
- mCornerRadius,
- mCornerRadius,
- mDrawPaint);
+ // Draw the thumbnail with the rounded corners
+ canvas.drawRoundRect(0, 0, getWidth(), getHeight(),
+ mConfig.taskViewRoundedCornerRadiusPx,
+ mConfig.taskViewRoundedCornerRadiusPx, mDrawPaint);
}
- @Override
- protected void onFinishInflate() {
- mBitmapAlpha = 0.9f;
- updateFilter();
+ /** Sets the thumbnail to a given bitmap. */
+ void setThumbnail(Bitmap bm) {
+ if (bm != null) {
+ mBitmapShader = new BitmapShader(bm, Shader.TileMode.CLAMP,
+ Shader.TileMode.CLAMP);
+ mDrawPaint.setShader(mBitmapShader);
+ mBitmapRect.set(0, 0, bm.getWidth(), bm.getHeight());
+ updateThumbnailScale();
+ } else {
+ mBitmapShader = null;
+ mDrawPaint.setShader(null);
+ }
+ updateThumbnailPaintFilter();
}
- private void updateFilter() {
+ /** Updates the paint to draw the thumbnail. */
+ void updateThumbnailPaintFilter() {
if (mInvisible) {
return;
}
- int mul = (int) ((1.0f - mDimAlpha) * mBitmapAlpha * 255);
- int add = (int) ((1.0f - mDimAlpha) * (1 - mBitmapAlpha) * 255);
+ int mul = (int) ((1.0f - mDimAlpha) * mThumbnailAlpha * 255);
+ int add = (int) ((1.0f - mDimAlpha) * (1 - mThumbnailAlpha) * 255);
if (mBitmapShader != null) {
mLightingColorFilter.setColorMultiply(Color.argb(255, mul, mul, mul));
mLightingColorFilter.setColorAdd(Color.argb(0, add, add, add));
mDrawPaint.setColorFilter(mLightingColorFilter);
mDrawPaint.setColor(0xffffffff);
} else {
- mDrawPaint.setColorFilter(null);
int grey = mul + add;
+ mDrawPaint.setColorFilter(null);
mDrawPaint.setColor(Color.argb(255, grey, grey, grey));
}
invalidate();
}
+ /** Updates the thumbnail shader's scale transform. */
+ void updateThumbnailScale() {
+ if (mBitmapShader != null) {
+ mScaleMatrix.setRectToRect(mBitmapRect, mLayoutRect, Matrix.ScaleToFit.FILL);
+ mBitmapShader.setLocalMatrix(mScaleMatrix);
+ }
+ }
+
/** Updates the clip rect based on the given task bar. */
- void enableTaskBarClip(View taskBar) {
+ void updateClipToTaskBar(View taskBar) {
mTaskBar = taskBar;
int top = (int) Math.max(0, taskBar.getTranslationY() +
taskBar.getMeasuredHeight() - 1);
@@ -133,75 +173,39 @@ public class TaskViewThumbnail extends View {
setClipBounds(mClipRect);
}
- void updateVisibility(int clipBottom) {
- boolean invisible = mTaskBar != null && getHeight() - clipBottom < mTaskBar.getHeight();
+ /** Updates the visibility of the the thumbnail. */
+ void updateThumbnailVisibility(int clipBottom) {
+ boolean invisible = mTaskBar != null && (getHeight() - clipBottom) <= mTaskBar.getHeight();
if (invisible != mInvisible) {
mInvisible = invisible;
if (!mInvisible) {
- updateFilter();
+ updateThumbnailPaintFilter();
}
invalidate();
}
}
- /** Binds the thumbnail view to the screenshot. */
- boolean bindToScreenshot(Bitmap ss) {
- setImageBitmap(ss);
- return ss != null;
- }
-
- /** Unbinds the thumbnail view from the screenshot. */
- void unbindFromScreenshot() {
- setImageBitmap(null);
+ /**
+ * Sets the dim alpha, only used when we are not using hardware layers.
+ * (see RecentsConfiguration.useHardwareLayers)
+ */
+ public void setDimAlpha(float dimAlpha) {
+ mDimAlpha = dimAlpha;
+ updateThumbnailPaintFilter();
}
/** Binds the thumbnail view to the task */
void rebindToTask(Task t) {
if (t.thumbnail != null) {
- setImageBitmap(t.thumbnail);
+ setThumbnail(t.thumbnail);
} else {
- setImageBitmap(null);
+ setThumbnail(null);
}
}
- public void setImageBitmap(Bitmap bm) {
- if (bm != null) {
- mBitmapShader = new BitmapShader(bm, Shader.TileMode.CLAMP,
- Shader.TileMode.CLAMP);
- mDrawPaint.setShader(mBitmapShader);
- mBitmapRect.set(0, 0, bm.getWidth(), bm.getHeight());
- updateBitmapScale();
- } else {
- mBitmapShader = null;
- mDrawPaint.setShader(null);
- }
- updateFilter();
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
- if (changed) {
- mLayoutRect.set(0, 0, getWidth(), getHeight());
- updateBitmapScale();
- }
- }
-
- private void updateBitmapScale() {
- if (mBitmapShader != null) {
- mScaleMatrix.setRectToRect(mBitmapRect, mLayoutRect, Matrix.ScaleToFit.FILL);
- mBitmapShader.setLocalMatrix(mScaleMatrix);
- }
- }
-
- public void setDimAlpha(float dimAlpha) {
- mDimAlpha = dimAlpha;
- updateFilter();
- }
-
/** Unbinds the thumbnail view from the task */
void unbindFromTask() {
- setImageBitmap(null);
+ setThumbnail(null);
}
/** Handles focus changes. */
@@ -217,54 +221,46 @@ public class TaskViewThumbnail extends View {
}
}
- /** Prepares for the enter recents animation. */
+ /**
+ * Prepares for the enter recents animation, this gets called before the the view
+ * is first visible and will be followed by a startEnterRecentsAnimation() call.
+ */
void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask) {
if (isTaskViewLaunchTargetTask) {
- mBitmapAlpha = 1f;
+ mThumbnailAlpha = 1f;
} else {
- mBitmapAlpha = mConfig.taskViewThumbnailAlpha;
+ mThumbnailAlpha = mConfig.taskViewThumbnailAlpha;
}
- updateFilter();
+ updateThumbnailPaintFilter();
}
- /** Animates this task thumbnail as it enters recents */
+ /** Animates this task thumbnail as it enters Recents. */
void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
startFadeAnimation(mConfig.taskViewThumbnailAlpha, delay,
mConfig.taskBarEnterAnimDuration, postAnimRunnable);
}
- /** Animates this task thumbnail as it exits recents */
+ /** Animates this task thumbnail as it exits Recents. */
void startLaunchTaskAnimation(Runnable postAnimRunnable) {
startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, postAnimRunnable);
}
- /** Animates the thumbnail alpha. */
+ /** Starts a new thumbnail alpha animation. */
void startFadeAnimation(float finalAlpha, int delay, int duration, final Runnable postAnimRunnable) {
- if (mAlphaAnimator != null) {
- mAlphaAnimator.cancel();
- }
- mAlphaAnimator = ValueAnimator.ofFloat(mBitmapAlpha, finalAlpha);
- mAlphaAnimator.addUpdateListener(mAlphaUpdateListener);
- mAlphaAnimator.setStartDelay(delay);
- mAlphaAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
- mAlphaAnimator.setDuration(duration);
- mAlphaAnimator.start();
+ Utilities.cancelAnimationWithoutCallbacks(mThumbnailAlphaAnimator);
+ mThumbnailAlphaAnimator = ValueAnimator.ofFloat(mThumbnailAlpha, finalAlpha);
+ mThumbnailAlphaAnimator.setStartDelay(delay);
+ mThumbnailAlphaAnimator.setDuration(duration);
+ mThumbnailAlphaAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
+ mThumbnailAlphaAnimator.addUpdateListener(mThumbnailAlphaUpdateListener);
if (postAnimRunnable != null) {
- mAlphaAnimator.addListener(new AnimatorListenerAdapter() {
- public boolean mCancelled;
-
- @Override
- public void onAnimationCancel(Animator animation) {
- mCancelled = true;
- }
-
+ mThumbnailAlphaAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- if (!mCancelled) {
- postAnimRunnable.run();
- }
+ postAnimRunnable.run();
}
});
}
+ mThumbnailAlphaAnimator.start();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index f5e5517..1b4bdf8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -69,6 +69,7 @@ import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
+import android.view.ViewParent;
import android.view.ViewStub;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
@@ -266,6 +267,7 @@ public abstract class BaseStatusBar extends SystemUI implements
if (DEBUG) {
Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent);
}
+ logActionClick(view);
// The intent we are sending is for the application, which
// won't have permission to immediately start an activity after
// the user switches to home. We know it is safe to do at this
@@ -295,7 +297,8 @@ public abstract class BaseStatusBar extends SystemUI implements
// close the shade if it was open
if (handled) {
- animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
+ animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
+ true /* force */);
visibilityChanged(false);
}
// Wait for activity start.
@@ -308,6 +311,37 @@ public abstract class BaseStatusBar extends SystemUI implements
}
}
+ private void logActionClick(View view) {
+ ViewParent parent = view.getParent();
+ String key = getNotificationKeyForParent(parent);
+ if (key == null) {
+ Log.w(TAG, "Couldn't determine notification for click.");
+ return;
+ }
+ int index = -1;
+ // If this is a default template, determine the index of the button.
+ if (view.getId() == com.android.internal.R.id.action0 &&
+ parent != null && parent instanceof ViewGroup) {
+ ViewGroup actionGroup = (ViewGroup) parent;
+ index = actionGroup.indexOfChild(view);
+ }
+ try {
+ mBarService.onNotificationActionClick(key, index);
+ } catch (RemoteException e) {
+ // Ignore
+ }
+ }
+
+ private String getNotificationKeyForParent(ViewParent parent) {
+ while (parent != null) {
+ if (parent instanceof ExpandableNotificationRow) {
+ return ((ExpandableNotificationRow) parent).getStatusBarNotification().getKey();
+ }
+ parent = parent.getParent();
+ }
+ return null;
+ }
+
private boolean superOnClickHandler(View view, PendingIntent pendingIntent,
Intent fillInIntent) {
return super.onClickHandler(view, pendingIntent, fillInIntent);
@@ -341,7 +375,8 @@ public abstract class BaseStatusBar extends SystemUI implements
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
if (BANNER_ACTION_SETUP.equals(action)) {
- animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
+ animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
+ true /* force */);
mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
@@ -766,7 +801,7 @@ public abstract class BaseStatusBar extends SystemUI implements
}
}
});
- animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
+ animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
return true;
}
}, false /* afterKeyguardGone */);
@@ -1531,7 +1566,8 @@ public abstract class BaseStatusBar extends SystemUI implements
}.start();
// close the shade if it was open
- animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
+ animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
+ true /* force */);
visibilityChanged(false);
return mIntent != null && mIntent.isActivity();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 9196dc8..556c423 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -158,6 +158,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
public void resetHeight() {
mMaxExpandHeight = 0;
mWasReset = true;
+ mActualHeight = 0;
onHeightReset();
requestLayout();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index b71c9bf..9154a48 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -49,7 +49,6 @@ public class SignalClusterView
private boolean mIsAirplaneMode = false;
private int mAirplaneIconId = 0;
private String mWifiDescription, mMobileDescription, mMobileTypeDescription;
- private boolean mRoaming;
private boolean mIsMobileTypeIconWide;
ViewGroup mWifiGroup, mMobileGroup;
@@ -58,6 +57,8 @@ public class SignalClusterView
View mWifiSignalSpacer;
private int mWideTypeIconStartPadding;
+ private int mEndPadding;
+ private int mEndPaddingNothingVisible;
public SignalClusterView(Context context) {
this(context, null);
@@ -88,6 +89,10 @@ public class SignalClusterView
super.onFinishInflate();
mWideTypeIconStartPadding = getContext().getResources().getDimensionPixelSize(
R.dimen.wide_type_icon_start_padding);
+ mEndPadding = getContext().getResources().getDimensionPixelSize(
+ R.dimen.signal_cluster_battery_padding);
+ mEndPaddingNothingVisible = getContext().getResources().getDimensionPixelSize(
+ R.dimen.no_signal_cluster_battery_padding);
}
@Override
@@ -143,14 +148,12 @@ public class SignalClusterView
@Override
public void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon,
- String contentDescription, String typeContentDescription, boolean roaming,
- boolean isTypeIconWide) {
+ String contentDescription, String typeContentDescription, boolean isTypeIconWide) {
mMobileVisible = visible;
mMobileStrengthId = strengthIcon;
mMobileTypeId = typeIcon;
mMobileDescription = contentDescription;
mMobileTypeDescription = typeContentDescription;
- mRoaming = roaming;
mIsMobileTypeIconWide = isTypeIconWide;
apply();
@@ -244,7 +247,7 @@ public class SignalClusterView
mWifiAirplaneSpacer.setVisibility(View.GONE);
}
- if (mRoaming && mMobileVisible && mWifiVisible) {
+ if (mMobileVisible && mMobileTypeId != 0 && mWifiVisible) {
mWifiSignalSpacer.setVisibility(View.VISIBLE);
} else {
mWifiSignalSpacer.setVisibility(View.GONE);
@@ -257,7 +260,10 @@ public class SignalClusterView
(mMobileVisible ? "VISIBLE" : "GONE"),
mMobileStrengthId, mMobileTypeId));
- mMobileType.setVisibility((mRoaming || mMobileTypeId != 0) ? View.VISIBLE : View.GONE);
+ mMobileType.setVisibility(mMobileTypeId != 0 ? View.VISIBLE : View.GONE);
+
+ boolean anythingVisible = mWifiVisible || mIsAirplaneMode || mMobileVisible || mVpnVisible;
+ setPaddingRelative(0, 0, anythingVisible ? mEndPadding : mEndPaddingNothingVisible, 0);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
index c5d06b9..682c01c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -122,9 +122,14 @@ public class DemoStatusIcons extends LinearLayout implements DemoMode {
}
String cast = args.getString("cast");
if (cast != null) {
- int iconId = cast.equals("cast") ? R.drawable.stat_sys_cast : 0;
+ int iconId = cast.equals("show") ? R.drawable.stat_sys_cast : 0;
updateSlot("cast", null, iconId);
}
+ String hotspot = args.getString("hotspot");
+ if (hotspot != null) {
+ int iconId = hotspot.equals("show") ? R.drawable.stat_sys_hotspot : 0;
+ updateSlot("hotspot", null, iconId);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index dd5df12..598a35c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -133,7 +133,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
if (action == ACTION_CLICK) {
if (host == mLockIcon) {
mPhoneStatusBar.animateCollapsePanels(
- CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
+ CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
return true;
} else if (host == mCameraImageView) {
launchCamera();
@@ -477,6 +477,11 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
public void onScreenTurnedOff(int why) {
updateLockIcon();
}
+
+ @Override
+ public void onKeyguardVisibilityChanged(boolean showing) {
+ updateLockIcon();
+ }
};
public void setKeyguardIndicationController(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 650a14f..40c9134 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -36,6 +36,8 @@ import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.UserInfoController;
+import java.text.NumberFormat;
+
/**
* The header group on Keyguard.
*/
@@ -150,7 +152,8 @@ public class KeyguardStatusBarView extends RelativeLayout
@Override
public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
- mBatteryLevel.setText(getResources().getString(R.string.battery_level_template, level));
+ String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
+ mBatteryLevel.setText(percentage);
boolean changed = mBatteryCharging != charging;
mBatteryCharging = charging;
if (changed) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index a6fccb6..c19bdff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -802,6 +802,7 @@ public class NotificationPanelView extends PanelView implements
requestPanelHeightUpdate();
mNotificationStackScroller.setInterceptDelegateEnabled(expanded);
mStatusBar.setQsExpanded(expanded);
+ mQsPanel.setExpanded(expanded);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index f74d2f4..3efaaff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -236,4 +236,8 @@ public class PanelBar extends FrameLayout {
public void onExpandingFinished() {
}
+
+ public void onClosingFinished() {
+
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index a7ff0bd..0ddda8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -68,7 +68,6 @@ public abstract class PanelView extends FrameLayout {
protected int mTouchSlop;
protected boolean mHintAnimationRunning;
private boolean mOverExpandedBeforeFling;
- private float mOriginalIndicationY;
private boolean mTouchAboveFalsingThreshold;
private int mUnlockFalsingThreshold;
@@ -107,7 +106,7 @@ public abstract class PanelView extends FrameLayout {
};
protected void onExpandingFinished() {
- mClosing = false;
+ endClosing();
mBar.onExpandingFinished();
}
@@ -250,9 +249,7 @@ public abstract class PanelView extends FrameLayout {
trackMovement(event);
if (!waitForTouchSlop || (mHeightAnimator != null && !mHintAnimationRunning) ||
mPeekPending || mPeekAnimator != null) {
- if (mHeightAnimator != null) {
- mHeightAnimator.cancel(); // end any outstanding animations
- }
+ cancelHeightAnimator();
cancelPeek();
mTouchSlopExceeded = (mHeightAnimator != null && !mHintAnimationRunning)
|| mPeekPending || mPeekAnimator != null;
@@ -293,9 +290,7 @@ public abstract class PanelView extends FrameLayout {
mInitialTouchY = y;
h = 0;
}
- if (mHeightAnimator != null) {
- mHeightAnimator.cancel(); // end any outstanding animations
- }
+ cancelHeightAnimator();
removeCallbacks(mPeekRunnable);
mPeekPending = false;
onTrackingStarted();
@@ -372,7 +367,7 @@ public abstract class PanelView extends FrameLayout {
}
protected void onTrackingStarted() {
- mClosing = false;
+ endClosing();
mTracking = true;
mCollapseAfterPeek = false;
mBar.onTrackingStarted(PanelView.this);
@@ -407,9 +402,7 @@ public abstract class PanelView extends FrameLayout {
mStatusBar.userActivity();
if (mHeightAnimator != null && !mHintAnimationRunning ||
mPeekPending || mPeekAnimator != null) {
- if (mHeightAnimator != null) {
- mHeightAnimator.cancel(); // end any outstanding animations
- }
+ cancelHeightAnimator();
cancelPeek();
mTouchSlopExceeded = true;
return true;
@@ -441,9 +434,7 @@ public abstract class PanelView extends FrameLayout {
trackMovement(event);
if (scrolledToBottom) {
if (h < -mTouchSlop && h < -Math.abs(x - mInitialTouchX)) {
- if (mHeightAnimator != null) {
- mHeightAnimator.cancel();
- }
+ cancelHeightAnimator();
mInitialOffsetOnTouch = mExpandedHeight;
mInitialTouchY = y;
mInitialTouchX = x;
@@ -461,6 +452,20 @@ public abstract class PanelView extends FrameLayout {
return false;
}
+ private void cancelHeightAnimator() {
+ if (mHeightAnimator != null) {
+ mHeightAnimator.cancel();
+ }
+ endClosing();
+ }
+
+ private void endClosing() {
+ if (mClosing) {
+ mClosing = false;
+ onClosingFinished();
+ }
+ }
+
private void initVelocityTracker() {
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
@@ -700,9 +705,7 @@ public abstract class PanelView extends FrameLayout {
mPeekRunnable.run();
}
} else if (!isFullyCollapsed() && !mTracking && !mClosing) {
- if (mHeightAnimator != null) {
- mHeightAnimator.cancel();
- }
+ cancelHeightAnimator();
mClosing = true;
notifyExpandingStarted();
if (delayed) {
@@ -785,13 +788,16 @@ public abstract class PanelView extends FrameLayout {
private void abortAnimations() {
cancelPeek();
- if (mHeightAnimator != null) {
- mHeightAnimator.cancel();
- }
+ cancelHeightAnimator();
removeCallbacks(mPostCollapseRunnable);
removeCallbacks(mFlingCollapseRunnable);
}
+ protected void onClosingFinished() {
+ mBar.onClosingFinished();
+ }
+
+
protected void startUnlockHintAnimation() {
// We don't need to hint the user if an animation is already running or the user is changing
@@ -841,16 +847,15 @@ public abstract class PanelView extends FrameLayout {
});
animator.start();
mHeightAnimator = animator;
- mOriginalIndicationY = mKeyguardBottomArea.getIndicationView().getY();
mKeyguardBottomArea.getIndicationView().animate()
- .y(mOriginalIndicationY - mHintDistance)
+ .translationY(-mHintDistance)
.setDuration(250)
.setInterpolator(mFastOutSlowInInterpolator)
.withEndAction(new Runnable() {
@Override
public void run() {
mKeyguardBottomArea.getIndicationView().animate()
- .y(mOriginalIndicationY)
+ .translationY(0)
.setDuration(450)
.setInterpolator(mBounceInterpolator)
.start();
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 9e3f0f6..9a33a36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -40,6 +40,7 @@ import android.app.Notification;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
+import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -95,6 +96,7 @@ import android.view.ViewPropertyAnimator;
import android.view.ViewStub;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateDecelerateInterpolator;
@@ -173,6 +175,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
DragDownHelper.DragDownCallback, ActivityStarter {
@@ -581,7 +584,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
addNavigationBar();
// Lastly, call to the icon policy to install/update all the icons.
- mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController);
+ mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController, mHotspotController);
mSettingsObserver.onChange(false); // set up
mHeadsUpObserver.onChange(true); // set up
@@ -798,7 +801,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
mUserInfoController = new UserInfoController(mContext);
mVolumeComponent = getComponent(VolumeComponent.class);
- mZenModeController = mVolumeComponent.getZenController();
+ if (mVolumeComponent != null) {
+ mZenModeController = mVolumeComponent.getZenController();
+ }
mCastController = new CastControllerImpl(mContext);
final SignalClusterView signalCluster =
(SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster);
@@ -2413,6 +2418,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
showBouncer();
disable(mDisabledUnmodified, true /* animate */);
+
+ // Trimming will happen later if Keyguard is showing - doing it here might cause a jank in
+ // the bouncer appear animation.
+ if (!mStatusBarKeyguardViewManager.isShowing()) {
+ WindowManagerGlobal.getInstance().trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
+ }
}
public boolean interceptTouchEvent(MotionEvent event) {
@@ -2955,6 +2966,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mSecurityController != null) {
mSecurityController.dump(fd, pw, args);
}
+ pw.println("SharedPreferences:");
+ for (Map.Entry<String, ?> entry : mContext.getSharedPreferences(mContext.getPackageName(),
+ Context.MODE_PRIVATE).getAll().entrySet()) {
+ pw.print(" "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue());
+ }
}
private String hunStateToString(Entry entry) {
@@ -3036,7 +3052,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
});
if (dismissShade) {
- animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
+ animateCollapsePanels(
+ CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
}
return true;
}
@@ -3725,7 +3742,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
public boolean onSpacePressed() {
if (mScreenOn != null && mScreenOn
&& (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) {
- animateCollapsePanels(0 /* flags */, true /* force */);
+ animateCollapsePanels(
+ CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */);
return true;
}
return false;
@@ -3779,6 +3797,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
runPostCollapseRunnables();
}
+ public void onClosingFinished() {
+ runPostCollapseRunnables();
+ }
+
public void onUnlockHintStarted() {
mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 47e1ab5..60d23ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -35,6 +35,7 @@ import com.android.internal.telephony.TelephonyIntents;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
+import com.android.systemui.statusbar.policy.HotspotController;
/**
* This class contains all of the policy about which icons are installed in the status
@@ -49,6 +50,7 @@ public class PhoneStatusBarPolicy {
private static final String SLOT_SYNC_ACTIVE = "sync_active";
private static final String SLOT_CAST = "cast";
+ private static final String SLOT_HOTSPOT = "hotspot";
private static final String SLOT_BLUETOOTH = "bluetooth";
private static final String SLOT_TTY = "tty";
private static final String SLOT_ZEN = "zen";
@@ -60,6 +62,7 @@ public class PhoneStatusBarPolicy {
private final StatusBarManager mService;
private final Handler mHandler = new Handler();
private final CastController mCast;
+ private final HotspotController mHotspot;
// Assume it's all good unless we hear otherwise. We don't always seem
// to get broadcasts that it *is* there.
@@ -102,9 +105,10 @@ public class PhoneStatusBarPolicy {
}
};
- public PhoneStatusBarPolicy(Context context, CastController cast) {
+ public PhoneStatusBarPolicy(Context context, CastController cast, HotspotController hotspot) {
mContext = context;
mCast = cast;
+ mHotspot = hotspot;
mService = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE);
// listen for broadcasts
@@ -152,6 +156,11 @@ public class PhoneStatusBarPolicy {
mService.setIcon(SLOT_CAST, R.drawable.stat_sys_cast, 0, null);
mService.setIconVisibility(SLOT_CAST, false);
mCast.addCallback(mCastCallback);
+
+ // hotspot
+ mService.setIcon(SLOT_HOTSPOT, R.drawable.stat_sys_hotspot, 0, null);
+ mService.setIconVisibility(SLOT_HOTSPOT, mHotspot.isHotspotEnabled());
+ mHotspot.addCallback(mHotspotCallback);
}
public void setZenMode(int zen) {
@@ -300,6 +309,13 @@ public class PhoneStatusBarPolicy {
mService.setIconVisibility(SLOT_CAST, isCasting);
}
+ private final HotspotController.Callback mHotspotCallback = new HotspotController.Callback() {
+ @Override
+ public void onHotspotChanged(boolean enabled) {
+ mService.setIconVisibility(SLOT_HOTSPOT, enabled);
+ }
+ };
+
private final CastController.Callback mCastCallback = new CastController.Callback() {
@Override
public void onCastDevicesChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 6411fb8..e4eae38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -20,7 +20,6 @@ import android.content.Context;
import android.content.res.Resources;
import android.util.AttributeSet;
import android.util.EventLog;
-import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
@@ -152,6 +151,12 @@ public class PhoneStatusBarView extends PanelBar {
}
@Override
+ public void onClosingFinished() {
+ super.onClosingFinished();
+ mBar.onClosingFinished();
+ }
+
+ @Override
public void onTrackingStopped(PanelView panel, boolean expand) {
super.onTrackingStopped(panel, expand);
mBar.onTrackingStopped(expand);
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 2dc08d4..a4db46a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -120,6 +120,7 @@ public class QSTileHost implements QSTile.Host {
tile.userSwitch(newUserId);
}
mSecurity.onUserSwitched(newUserId);
+ mNetwork.onUserSwitched(newUserId);
mObserver.register();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index b0f3ea1..247252c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -48,6 +48,8 @@ import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.UserInfoController;
+import java.text.NumberFormat;
+
/**
* The view to manage the header area in the expanded status bar.
*/
@@ -300,9 +302,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
updateSystemIconsLayoutParams();
updateClickTargets();
updateMultiUserSwitch();
- if (mQSPanel != null) {
- mQSPanel.setExpanded(mExpanded);
- }
updateClockScale();
updateAvatarScale();
updateClockLp();
@@ -395,7 +394,8 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
@Override
public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
- mBatteryLevel.setText(getResources().getString(R.string.battery_level_template, level));
+ String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
+ mBatteryLevel.setText(percentage);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 55c861a..65d231e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import android.content.ComponentCallbacks2;
import android.content.Context;
import android.os.Bundle;
import android.os.RemoteException;
@@ -24,6 +25,7 @@ import android.util.Slog;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManagerGlobal;
import com.android.internal.policy.IKeyguardShowCallback;
import com.android.internal.widget.LockPatternUtils;
@@ -268,6 +270,8 @@ public class StatusBarKeyguardViewManager {
public void run() {
mStatusBarWindowManager.setKeyguardFadingAway(false);
mPhoneStatusBar.finishKeyguardFadingAway();
+ WindowManagerGlobal.getInstance().trimMemory(
+ ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
}
});
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java
index dcda2c7..b89aa8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java
@@ -133,6 +133,7 @@ public class TrustDrawable extends Drawable {
if (!mAnimating) {
mAnimating = true;
updateState(true);
+ invalidateSelf();
}
}
@@ -146,18 +147,21 @@ public class TrustDrawable extends Drawable {
mState = STATE_UNSET;
mCurAlpha = 0;
mCurInnerRadius = mInnerRadiusEnter;
+ invalidateSelf();
}
}
public void setTrustManaged(boolean trustManaged) {
if (trustManaged == mTrustManaged && mState != STATE_UNSET) return;
mTrustManaged = trustManaged;
- if (mAnimating) {
- updateState(true);
- }
+ updateState(true);
}
- private void updateState(boolean animate) {
+ private void updateState(boolean allowTransientState) {
+ if (!mAnimating) {
+ return;
+ }
+
int nextState = mState;
if (mState == STATE_UNSET) {
nextState = mTrustManaged ? STATE_ENTERING : STATE_GONE;
@@ -170,7 +174,7 @@ public class TrustDrawable extends Drawable {
} else if (mState == STATE_EXITING) {
if (mTrustManaged) nextState = STATE_ENTERING;
}
- if (!animate) {
+ if (!allowTransientState) {
if (nextState == STATE_ENTERING) nextState = STATE_VISIBLE;
if (nextState == STATE_EXITING) nextState = STATE_GONE;
}
@@ -200,9 +204,8 @@ public class TrustDrawable extends Drawable {
mState = nextState;
if (mCurAnimator != null) {
mCurAnimator.start();
- } else {
- invalidateSelf();
}
+ invalidateSelf();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiAccessPointController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointController.java
index b800fbf..0a385d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiAccessPointController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessPointController.java
@@ -16,15 +16,20 @@
package com.android.systemui.statusbar.policy;
+import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.ActionListener;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -39,9 +44,13 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-public class WifiAccessPointController {
- private static final String TAG = "WifiAccessPointController";
- private static final boolean DEBUG = false;
+public class AccessPointController {
+ private static final String TAG = "AccessPointController";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ // This string extra specifies a network to open the connect dialog on, so the user can enter
+ // network credentials. This is used by quick settings for secured networks.
+ private static final String EXTRA_START_CONNECT_SSID = "wifi_start_connect_ssid";
private static final int[] ICONS = {
R.drawable.ic_qs_wifi_0,
@@ -54,13 +63,26 @@ public class WifiAccessPointController {
private final Context mContext;
private final ArrayList<AccessPointCallback> mCallbacks = new ArrayList<AccessPointCallback>();
private final WifiManager mWifiManager;
+ private final UserManager mUserManager;
private final Receiver mReceiver = new Receiver();
private boolean mScanning;
+ private int mCurrentUser;
- public WifiAccessPointController(Context context) {
+ public AccessPointController(Context context) {
mContext = context;
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
+ mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mCurrentUser = ActivityManager.getCurrentUser();
+ }
+
+ public boolean canConfigWifi() {
+ return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_WIFI,
+ new UserHandle(mCurrentUser));
+ }
+
+ void onUserSwitched(int newUserId) {
+ mCurrentUser = newUserId;
}
public void addCallback(AccessPointCallback callback) {
@@ -81,22 +103,31 @@ public class WifiAccessPointController {
if (mScanning) return;
if (DEBUG) Log.d(TAG, "scan!");
mScanning = mWifiManager.startScan();
+ // Grab current networks immediately while we wait for scan.
+ updateAccessPoints();
}
- public void connect(AccessPoint ap) {
- if (ap == null || ap.networkId < 0) return;
+ public boolean connect(AccessPoint ap) {
+ if (ap == null) return false;
if (DEBUG) Log.d(TAG, "connect networkId=" + ap.networkId);
- mWifiManager.connect(ap.networkId, new ActionListener() {
- @Override
- public void onSuccess() {
- if (DEBUG) Log.d(TAG, "connect success");
- }
-
- @Override
- public void onFailure(int reason) {
- if (DEBUG) Log.d(TAG, "connect failure reason=" + reason);
+ if (ap.networkId < 0) {
+ // Unknown network, need to add it.
+ if (ap.hasSecurity) {
+ Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
+ intent.putExtra(EXTRA_START_CONNECT_SSID, ap.ssid);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+ return true;
+ } else {
+ WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "\"" + ap.ssid + "\"";
+ config.allowedKeyManagement.set(KeyMgmt.NONE);
+ mWifiManager.connect(config, mConnectListener);
}
- });
+ } else {
+ mWifiManager.connect(ap.networkId, mConnectListener);
+ }
+ return false;
}
private void fireCallback(AccessPoint[] aps) {
@@ -139,23 +170,40 @@ public class WifiAccessPointController {
}
final String ssid = scanResult.SSID;
if (TextUtils.isEmpty(ssid) || ssids.contains(ssid)) continue;
- if (!configured.containsKey(ssid)) continue;
ssids.add(ssid);
final WifiConfiguration config = configured.get(ssid);
final int level = WifiManager.calculateSignalLevel(scanResult.level, ICONS.length);
final AccessPoint ap = new AccessPoint();
+ ap.isConfigured = config != null;
ap.networkId = config != null ? config.networkId : AccessPoint.NO_NETWORK;
ap.ssid = ssid;
ap.iconId = ICONS[level];
ap.isConnected = ap.networkId != AccessPoint.NO_NETWORK
&& ap.networkId == connectedNetworkId;
ap.level = level;
+ // Based on Settings AccessPoint#getSecurity, keep up to date
+ // with better methods of determining no security or not.
+ ap.hasSecurity = scanResult.capabilities.contains("WEP")
+ || scanResult.capabilities.contains("PSK")
+ || scanResult.capabilities.contains("EAP");
aps.add(ap);
}
Collections.sort(aps, mByStrength);
fireCallback(aps.toArray(new AccessPoint[aps.size()]));
}
+ private final ActionListener mConnectListener = new ActionListener() {
+ @Override
+ public void onSuccess() {
+ if (DEBUG) Log.d(TAG, "connect success");
+ }
+
+ @Override
+ public void onFailure(int reason) {
+ if (DEBUG) Log.d(TAG, "connect failure reason=" + reason);
+ }
+ };
+
private final Comparator<AccessPoint> mByStrength = new Comparator<AccessPoint> () {
@Override
public int compare(AccessPoint lhs, AccessPoint rhs) {
@@ -163,7 +211,7 @@ public class WifiAccessPointController {
}
private int score(AccessPoint ap) {
- return ap.level + (ap.isConnected ? 10 : 0);
+ return ap.level + (ap.isConnected ? 20 : 0) + (ap.isConfigured ? 10 : 0);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
index 6f021ac..33f7aff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java
@@ -308,7 +308,11 @@ public class FlashlightController {
new CameraCaptureSession.StateListener() {
@Override
public void onConfigured(CameraCaptureSession session) {
- mSession = session;
+ if (session.getDevice() == mCameraDevice) {
+ mSession = session;
+ } else {
+ session.close();
+ }
postUpdateFlashlight();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 2ed9366..bb29d01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -39,11 +39,13 @@ public interface NetworkController {
void addAccessPointCallback(AccessPointCallback callback);
void removeAccessPointCallback(AccessPointCallback callback);
void scanForAccessPoints();
- void connect(AccessPoint ap);
+ boolean connect(AccessPoint ap);
boolean isMobileDataSupported();
boolean isMobileDataEnabled();
void setMobileDataEnabled(boolean enabled);
DataUsageInfo getDataUsageInfo();
+ boolean canConfigWifi();
+ void onUserSwitched(int newUserId);
public interface AccessPointCallback {
void onAccessPointsChanged(AccessPoint[] accessPoints);
@@ -56,6 +58,8 @@ public interface NetworkController {
public int iconId;
public String ssid;
public boolean isConnected;
+ public boolean isConfigured;
+ public boolean hasSecurity;
public int level; // 0 - 5
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 3625997..6c0b425 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -164,12 +164,11 @@ public class NetworkControllerImpl extends BroadcastReceiver
public interface SignalCluster {
void setWifiIndicators(boolean visible, int strengthIcon, String contentDescription);
void setMobileDataIndicators(boolean visible, int strengthIcon, int typeIcon,
- String contentDescription, String typeContentDescription, boolean roaming,
- boolean isTypeIconWide);
+ String contentDescription, String typeContentDescription, boolean isTypeIconWide);
void setIsAirplaneMode(boolean is, int airplaneIcon);
}
- private final WifiAccessPointController mAccessPoints;
+ private final AccessPointController mAccessPoints;
private final MobileDataController mMobileDataController;
/**
@@ -240,7 +239,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
updateAirplaneMode();
mLastLocale = mContext.getResources().getConfiguration().locale;
- mAccessPoints = new WifiAccessPointController(mContext);
+ mAccessPoints = new AccessPointController(mContext);
mMobileDataController = new MobileDataController(mContext);
mMobileDataController.setCallback(new MobileDataController.Callback() {
@Override
@@ -250,6 +249,16 @@ public class NetworkControllerImpl extends BroadcastReceiver
});
}
+ @Override
+ public boolean canConfigWifi() {
+ return mAccessPoints.canConfigWifi();
+ }
+
+ @Override
+ public void onUserSwitched(int newUserId) {
+ mAccessPoints.onUserSwitched(newUserId);
+ }
+
private void notifyMobileDataEnabled(boolean enabled) {
for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) {
cb.onMobileDataEnabled(enabled);
@@ -314,8 +323,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
}
@Override
- public void connect(AccessPoint ap) {
- mAccessPoints.connect(ap);
+ public boolean connect(AccessPoint ap) {
+ return mAccessPoints.connect(ap);
}
@Override
@@ -386,7 +395,6 @@ public class NetworkControllerImpl extends BroadcastReceiver
mDataTypeIconId,
mContentDescriptionWimax,
mContentDescriptionDataType,
- mDataTypeIconId == TelephonyIcons.ROAMING_ICON,
false /* isTypeIconWide */ );
} else {
// normal mobile data
@@ -396,7 +404,6 @@ public class NetworkControllerImpl extends BroadcastReceiver
mDataTypeIconId,
mContentDescriptionPhoneSignal,
mContentDescriptionDataType,
- mDataTypeIconId == TelephonyIcons.ROAMING_ICON,
isTypeIconWide(mDataTypeIconId));
}
cluster.setIsAirplaneMode(mAirplaneMode, mAirplaneIconId);
@@ -1606,7 +1613,6 @@ public class NetworkControllerImpl extends BroadcastReceiver
mDemoDataTypeIconId,
"Demo",
"Demo",
- mDemoDataTypeIconId == TelephonyIcons.ROAMING_ICON,
isTypeIconWide(mDemoDataTypeIconId));
}
refreshViews();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
deleted file mode 100644
index f339401..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Prefs.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2010 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.Context;
-import android.content.SharedPreferences;
-
-public class Prefs {
- private static final String SHARED_PREFS_NAME = "status_bar";
-
- public static SharedPreferences read(Context context) {
- return context.getSharedPreferences(Prefs.SHARED_PREFS_NAME, Context.MODE_PRIVATE);
- }
-
- public static SharedPreferences.Editor edit(Context context) {
- return context.getSharedPreferences(Prefs.SHARED_PREFS_NAME, Context.MODE_PRIVATE).edit();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index eb808c2..5c7909a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -571,6 +571,9 @@ public class UserSwitcherController {
cancel();
} else {
dismiss();
+ if (ActivityManager.isUserAMonkey()) {
+ return;
+ }
UserInfo user = mUserManager.createSecondaryUser(
mContext.getString(R.string.user_new_user_name), 0 /* flags */);
if (user == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index 0586a83..0fe6d89 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -1,7 +1,6 @@
package com.android.systemui.volume;
import android.content.Context;
-import android.content.Intent;
import android.content.res.Configuration;
import android.database.ContentObserver;
import android.media.AudioManager;
@@ -11,13 +10,10 @@ import android.media.session.ISessionController;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Handler;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
-import android.view.WindowManagerGlobal;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
@@ -53,6 +49,7 @@ public class VolumeUI extends SystemUI {
private final Handler mHandler = new Handler();
+ private boolean mEnabled;
private AudioManager mAudioManager;
private MediaSessionManager mMediaSessionManager;
private VolumeController mVolumeController;
@@ -63,6 +60,8 @@ public class VolumeUI extends SystemUI {
@Override
public void start() {
+ mEnabled = mContext.getResources().getBoolean(R.bool.enable_volume_ui);
+ if (!mEnabled) return;
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
mMediaSessionManager = (MediaSessionManager) mContext
.getSystemService(Context.MEDIA_SESSION_SERVICE);
@@ -84,6 +83,7 @@ public class VolumeUI extends SystemUI {
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.print("mEnabled="); pw.println(mEnabled);
if (mPanel != null) {
mPanel.dump(fd, pw, args);
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index ea431ae..c840f17 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -31,6 +31,7 @@ import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.notification.Condition;
import android.service.notification.ZenModeConfig;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.MathUtils;
@@ -220,7 +221,8 @@ public class ZenModePanel extends LinearLayout {
mBucketIndex = -1;
} else {
mBucketIndex = DEFAULT_BUCKET_INDEX;
- mTimeCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
+ mTimeCondition = ZenModeConfig.toTimeCondition(mContext,
+ MINUTE_BUCKETS[mBucketIndex]);
}
if (DEBUG) Log.d(mTag, "Initial bucket index: " + mBucketIndex);
mConditions = null; // reset conditions
@@ -339,9 +341,11 @@ public class ZenModePanel extends LinearLayout {
if (condition == null) return null;
final long time = ZenModeConfig.tryParseCountdownConditionId(condition.id);
if (time == 0) return null;
- final long span = time - System.currentTimeMillis();
+ final long now = System.currentTimeMillis();
+ final long span = time - now;
if (span <= 0 || span > MAX_BUCKET_MINUTES * MINUTES_MS) return null;
- return ZenModeConfig.toTimeCondition(time, Math.round(span / (float) MINUTES_MS));
+ return ZenModeConfig.toTimeCondition(mContext,
+ time, Math.round(span / (float) MINUTES_MS), now);
}
private void handleUpdateConditions(Condition[] conditions) {
@@ -395,7 +399,7 @@ public class ZenModePanel extends LinearLayout {
if (favoriteIndex == -1) {
getConditionTagAt(FOREVER_CONDITION_INDEX).rb.setChecked(true);
} else {
- mTimeCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[favoriteIndex]);
+ mTimeCondition = ZenModeConfig.toTimeCondition(mContext, MINUTE_BUCKETS[favoriteIndex]);
mBucketIndex = favoriteIndex;
bind(mTimeCondition, mZenConditions.getChildAt(TIME_CONDITION_INDEX));
getConditionTagAt(TIME_CONDITION_INDEX).rb.setChecked(true);
@@ -430,7 +434,8 @@ public class ZenModePanel extends LinearLayout {
}
tag.condition = condition;
tag.rb.setEnabled(enabled);
- if (sameConditionId(mSessionExitCondition, tag.condition)) {
+ if (mSessionExitCondition != null
+ && sameConditionId(mSessionExitCondition, tag.condition)) {
tag.rb.setChecked(true);
}
tag.rb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@@ -450,16 +455,32 @@ public class ZenModePanel extends LinearLayout {
}
});
- if (tag.title == null) {
- tag.title = (TextView) row.findViewById(android.R.id.title);
+ if (tag.lines == null) {
+ tag.lines = row.findViewById(android.R.id.content);
}
+ if (tag.line1 == null) {
+ tag.line1 = (TextView) row.findViewById(android.R.id.text1);
+ }
+ if (tag.line2 == null) {
+ tag.line2 = (TextView) row.findViewById(android.R.id.text2);
+ }
+ final String line1, line2;
if (condition == null) {
- tag.title.setText(mContext.getString(com.android.internal.R.string.zen_mode_forever));
+ line1 = mContext.getString(com.android.internal.R.string.zen_mode_forever);
+ line2 = null;
+ } else {
+ line1 = !TextUtils.isEmpty(condition.line1) ? condition.line1 : condition.summary;
+ line2 = condition.line2;
+ }
+ tag.line1.setText(line1);
+ if (TextUtils.isEmpty(line2)) {
+ tag.line2.setVisibility(GONE);
} else {
- tag.title.setText(condition.summary);
+ tag.line2.setVisibility(VISIBLE);
+ tag.line2.setText(line2);
}
- tag.title.setEnabled(enabled);
- tag.title.setAlpha(enabled ? 1 : .4f);
+ tag.lines.setEnabled(enabled);
+ tag.lines.setAlpha(enabled ? 1 : .4f);
final ImageView button1 = (ImageView) row.findViewById(android.R.id.button1);
button1.setOnClickListener(new OnClickListener() {
@@ -476,7 +497,7 @@ public class ZenModePanel extends LinearLayout {
onClickTimeButton(row, tag, true /*up*/);
}
});
- tag.title.setOnClickListener(new OnClickListener() {
+ tag.lines.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
tag.rb.setChecked(true);
@@ -491,7 +512,8 @@ public class ZenModePanel extends LinearLayout {
} else {
final long span = time - System.currentTimeMillis();
button1.setEnabled(span > MIN_BUCKET_MINUTES * MINUTES_MS);
- final Condition maxCondition = ZenModeConfig.toTimeCondition(MAX_BUCKET_MINUTES);
+ final Condition maxCondition = ZenModeConfig.toTimeCondition(mContext,
+ MAX_BUCKET_MINUTES);
button2.setEnabled(!Objects.equals(condition.summary, maxCondition.summary));
}
@@ -504,7 +526,7 @@ public class ZenModePanel extends LinearLayout {
// wire up interaction callbacks for newly-added condition rows
if (convertView == null) {
Interaction.register(tag.rb, mInteractionCallback);
- Interaction.register(tag.title, mInteractionCallback);
+ Interaction.register(tag.lines, mInteractionCallback);
Interaction.register(button1, mInteractionCallback);
Interaction.register(button2, mInteractionCallback);
}
@@ -524,7 +546,7 @@ public class ZenModePanel extends LinearLayout {
return;
}
announceForAccessibility(mContext.getString(R.string.zen_mode_and_condition, modeText,
- tag.title.getText()));
+ tag.line1.getText()));
}
private void onClickTimeButton(View row, ConditionTag tag, boolean up) {
@@ -541,18 +563,21 @@ public class ZenModePanel extends LinearLayout {
final long bucketTime = now + bucketMinutes * MINUTES_MS;
if (up && bucketTime > time || !up && bucketTime < time) {
mBucketIndex = j;
- newCondition = ZenModeConfig.toTimeCondition(bucketTime, bucketMinutes);
+ newCondition = ZenModeConfig.toTimeCondition(mContext,
+ bucketTime, bucketMinutes, now);
break;
}
}
if (newCondition == null) {
mBucketIndex = DEFAULT_BUCKET_INDEX;
- newCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
+ newCondition = ZenModeConfig.toTimeCondition(mContext,
+ MINUTE_BUCKETS[mBucketIndex]);
}
} else {
// on a known index, simply increment or decrement
mBucketIndex = Math.max(0, Math.min(N - 1, mBucketIndex + (up ? 1 : -1)));
- newCondition = ZenModeConfig.toTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
+ newCondition = ZenModeConfig.toTimeCondition(mContext,
+ MINUTE_BUCKETS[mBucketIndex]);
}
mTimeCondition = newCondition;
bind(mTimeCondition, row);
@@ -639,7 +664,9 @@ public class ZenModePanel extends LinearLayout {
// used as the view tag on condition rows
private static class ConditionTag {
RadioButton rb;
- TextView title;
+ View lines;
+ TextView line1;
+ TextView line2;
Condition condition;
}
@@ -690,7 +717,7 @@ public class ZenModePanel extends LinearLayout {
}
private SharedPreferences prefs() {
- return mContext.getSharedPreferences(ZenModePanel.class.getSimpleName(), 0);
+ return mContext.getSharedPreferences(mContext.getPackageName(), 0);
}
private void updateMinuteIndex() {