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/recents/AlternateRecentsComponent.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java64
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Constants.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Utilities.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java90
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java93
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java121
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java189
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java215
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/PiecewiseLinearIndentationFunctor.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackIndentationFunctor.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java50
35 files changed, 939 insertions, 358 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 3ef8316..19a1b11 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -255,15 +255,10 @@ public class AlternateRecentsComponent {
/** Loads the first task thumbnail */
Bitmap loadFirstTaskThumbnail() {
SystemServicesProxy ssp = mSystemServicesProxy;
- List<ActivityManager.RecentTaskInfo> tasks = ssp.getRecentTasks(1,
- UserHandle.CURRENT.getIdentifier());
- for (ActivityManager.RecentTaskInfo t : tasks) {
- // Skip tasks in the home stack
- if (ssp.isInHomeStack(t.persistentId)) {
- return null;
- }
+ List<ActivityManager.RunningTaskInfo> tasks = ssp.getRunningTasks(1);
- return ssp.getTaskThumbnail(t.persistentId);
+ for (ActivityManager.RunningTaskInfo t : tasks) {
+ return ssp.getTaskThumbnail(t.id);
}
return null;
}
@@ -286,17 +281,6 @@ public class AlternateRecentsComponent {
return (tasks.size() > 1);
}
- /** Returns whether the base intent of the top task stack was launched with the flag
- * Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS. */
- boolean isTopTaskExcludeFromRecents(List<ActivityManager.RecentTaskInfo> tasks) {
- if (tasks.size() > 0) {
- ActivityManager.RecentTaskInfo t = tasks.get(0);
- Console.log(t.baseIntent.toString());
- return (t.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
- }
- return false;
- }
-
/** Converts from the device rotation to the degree */
float getDegreesForRotation(int value) {
switch (value) {
@@ -416,16 +400,14 @@ public class AlternateRecentsComponent {
}
// Otherwise, Recents is not the front-most activity and we should animate into it. If
- // the activity at the root of the top task stack is excluded from recents, or if that
- // task stack is in the home stack, then we just do a simple transition. Otherwise, we
- // animate to the rects defined by the Recents service, which can differ depending on the
- // number of items in the list.
+ // the activity at the root of the top task stack in the home stack, then we just do a
+ // simple transition. Otherwise, we animate to the rects defined by the Recents service,
+ // which can differ depending on the number of items in the list.
List<ActivityManager.RecentTaskInfo> recentTasks =
- ssp.getRecentTasks(4, UserHandle.CURRENT.getIdentifier());
+ ssp.getRecentTasks(2, UserHandle.CURRENT.getIdentifier());
Rect taskRect = hasMultipleRecentsTask(recentTasks) ? mMultipleCountFirstTaskRect :
mSingleCountFirstTaskRect;
- boolean isTaskExcludedFromRecents = isTopTaskExcludeFromRecents(recentTasks);
- boolean useThumbnailTransition = !isTopTaskHome && !isTaskExcludedFromRecents &&
+ boolean useThumbnailTransition = !isTopTaskHome &&
hasValidTaskRects();
if (useThumbnailTransition) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java b/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java
deleted file mode 100644
index 95ab8e8..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.android.systemui.recents;
-
-import android.animation.TimeInterpolator;
-
-/**
- * A pre-baked bezier-curved interpolator for quantum-paper transitions.
- */
-public class BakedBezierInterpolator implements TimeInterpolator {
- public static final BakedBezierInterpolator INSTANCE = new BakedBezierInterpolator();
-
- /**
- * Use the INSTANCE variable instead of instantiating.
- */
- private BakedBezierInterpolator() {
- super();
- }
-
- /**
- * Lookup table values.
- * Generated using a Bezier curve from (0,0) to (1,1) with control points:
- * P0 (0,0)
- * P1 (0.4, 0)
- * P2 (0.2, 1.0)
- * P3 (1.0, 1.0)
- *
- * Values sampled with x at regular intervals between 0 and 1.
- */
- private static final float[] VALUES = new float[] {
- 0.0f, 0.0002f, 0.0009f, 0.0019f, 0.0036f, 0.0059f, 0.0086f, 0.0119f, 0.0157f, 0.0209f,
- 0.0257f, 0.0321f, 0.0392f, 0.0469f, 0.0566f, 0.0656f, 0.0768f, 0.0887f, 0.1033f, 0.1186f,
- 0.1349f, 0.1519f, 0.1696f, 0.1928f, 0.2121f, 0.237f, 0.2627f, 0.2892f, 0.3109f, 0.3386f,
- 0.3667f, 0.3952f, 0.4241f, 0.4474f, 0.4766f, 0.5f, 0.5234f, 0.5468f, 0.5701f, 0.5933f,
- 0.6134f, 0.6333f, 0.6531f, 0.6698f, 0.6891f, 0.7054f, 0.7214f, 0.7346f, 0.7502f, 0.763f,
- 0.7756f, 0.7879f, 0.8f, 0.8107f, 0.8212f, 0.8326f, 0.8415f, 0.8503f, 0.8588f, 0.8672f,
- 0.8754f, 0.8833f, 0.8911f, 0.8977f, 0.9041f, 0.9113f, 0.9165f, 0.9232f, 0.9281f, 0.9328f,
- 0.9382f, 0.9434f, 0.9476f, 0.9518f, 0.9557f, 0.9596f, 0.9632f, 0.9662f, 0.9695f, 0.9722f,
- 0.9753f, 0.9777f, 0.9805f, 0.9826f, 0.9847f, 0.9866f, 0.9884f, 0.9901f, 0.9917f, 0.9931f,
- 0.9944f, 0.9955f, 0.9964f, 0.9973f, 0.9981f, 0.9986f, 0.9992f, 0.9995f, 0.9998f, 1.0f, 1.0f
- };
-
- private static final float STEP_SIZE = 1.0f / (VALUES.length - 1);
-
- @Override
- public float getInterpolation(float input) {
- if (input >= 1.0f) {
- return 1.0f;
- }
-
- if (input <= 0f) {
- return 0f;
- }
-
- int position = Math.min(
- (int)(input * (VALUES.length - 1)),
- VALUES.length - 2);
-
- float quantized = position * STEP_SIZE;
- float difference = input - quantized;
- float weight = difference / STEP_SIZE;
-
- return VALUES[position] + weight * (VALUES[position + 1] - VALUES[position]);
- }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 1d6a76c..90998da 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -32,7 +32,7 @@ public class Constants {
// Enables the use of theme colors as the task bar background
public static final boolean EnableTaskBarThemeColors = true;
// Enables the info pane on long-press
- public static final boolean EnableInfoPane = true;
+ public static final boolean EnableInfoPane = false;
// Enables the search bar layout
public static final boolean EnableSearchLayout = true;
// Enables the dynamic shadows behind each task
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 463cf74..9afc1cb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -23,6 +23,8 @@ import android.content.res.Resources;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.TypedValue;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
import com.android.systemui.R;
@@ -42,6 +44,8 @@ public class RecentsConfiguration {
public float animationPxMovementPerSecond;
+ public Interpolator defaultBezierInterpolator;
+
public int filteringCurrentViewsMinAnimDuration;
public int filteringNewViewsMinAnimDuration;
public int taskBarEnterAnimDuration;
@@ -121,7 +125,6 @@ public class RecentsConfiguration {
res.getDimensionPixelSize(R.dimen.recents_task_view_z_increment);
searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height);
-
taskBarViewDefaultBackgroundColor =
res.getColor(R.color.recents_task_bar_default_background_color);
taskBarViewDefaultTextColor =
@@ -131,6 +134,9 @@ public class RecentsConfiguration {
taskBarViewDarkTextColor =
res.getColor(R.color.recents_task_bar_dark_text_color);
+ defaultBezierInterpolator = AnimationUtils.loadInterpolator(context,
+ com.android.internal.R.interpolator.fast_out_slow_in);
+
// Update the search widget id
SharedPreferences settings = context.getSharedPreferences(context.getPackageName(), 0);
searchBarAppWidgetId = settings.getInt(Constants.Values.App.Key_SearchAppWidgetId, -1);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index f3e411f..1ca0476 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -35,7 +35,6 @@ import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -362,7 +361,7 @@ public class RecentsTaskLoader {
return mSystemServicesProxy;
}
- private List<ActivityManager.RecentTaskInfo> getRecentTasks(Context context) {
+ private List<ActivityManager.RecentTaskInfo> getRecentTasks() {
long t1 = System.currentTimeMillis();
SystemServicesProxy ssp = mSystemServicesProxy;
@@ -375,23 +374,6 @@ public class RecentsTaskLoader {
Console.log(Constants.Log.App.TaskDataLoader,
"[RecentsTaskLoader|tasks]", "" + tasks.size());
- // Remove home/recents tasks
- Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
- while (iter.hasNext()) {
- ActivityManager.RecentTaskInfo t = iter.next();
-
- // Skip tasks in the home stack
- if (ssp.isInHomeStack(t.persistentId)) {
- iter.remove();
- continue;
- }
- // Skip tasks from this Recents package
- if (t.baseIntent.getComponent().getPackageName().equals(context.getPackageName())) {
- iter.remove();
- continue;
- }
- }
-
return tasks;
}
@@ -408,7 +390,7 @@ public class RecentsTaskLoader {
// Get the recent tasks
SystemServicesProxy ssp = mSystemServicesProxy;
- List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(context);
+ List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks();
// Add each task to the task stack
t1 = System.currentTimeMillis();
@@ -554,14 +536,16 @@ public class RecentsTaskLoader {
}
/** Completely removes the resource data from the pool. */
- public void deleteTaskData(Task t) {
+ public void deleteTaskData(Task t, boolean notifyTaskDataUnloaded) {
Console.log(Constants.Log.App.TaskDataLoader,
"[RecentsTaskLoader|deleteTask]", t);
mLoadQueue.removeTask(t);
mThumbnailCache.remove(t.key);
mApplicationIconCache.remove(t.key);
- t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon);
+ if (notifyTaskDataUnloaded) {
+ t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon);
+ }
}
/** Stops the task loader and clears all pending tasks */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index b41555f..8d82883 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -30,7 +30,6 @@ import android.content.pm.ActivityInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
-import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
@@ -40,6 +39,7 @@ import android.os.UserManager;
import android.util.Pair;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import java.util.Random;
@@ -54,7 +54,7 @@ public class SystemServicesProxy {
IPackageManager mIpm;
UserManager mUm;
SearchManager mSm;
- String mPackage;
+ String mRecentsPackage;
ComponentName mAssistComponent;
Bitmap mDummyIcon;
@@ -67,7 +67,7 @@ public class SystemServicesProxy {
mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
mIpm = AppGlobals.getPackageManager();
mSm = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
- mPackage = context.getPackageName();
+ mRecentsPackage = context.getPackageName();
// Resolve the assist intent
Intent assist = mSm.getAssistIntent(context, false);
@@ -83,14 +83,14 @@ public class SystemServicesProxy {
}
/** Returns a list of the recents tasks */
- public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numTasks, int userId) {
+ public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numLatestTasks, int userId) {
if (mAm == null) return null;
// If we are mocking, then create some recent tasks
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
ArrayList<ActivityManager.RecentTaskInfo> tasks =
new ArrayList<ActivityManager.RecentTaskInfo>();
- int count = Math.min(numTasks, Constants.DebugFlags.App.SystemServicesProxyMockTaskCount);
+ int count = Math.min(numLatestTasks, Constants.DebugFlags.App.SystemServicesProxyMockTaskCount);
for (int i = 0; i < count; i++) {
// Create a dummy component name
int packageIndex = i % Constants.DebugFlags.App.SystemServicesProxyMockPackageCount;
@@ -114,9 +114,43 @@ public class SystemServicesProxy {
return tasks;
}
- return mAm.getRecentTasksForUser(numTasks,
+ // Remove home/recents/excluded tasks
+ int minNumTasksToQuery = 10;
+ int numTasksToQuery = Math.max(minNumTasksToQuery, numLatestTasks);
+ List<ActivityManager.RecentTaskInfo> tasks = mAm.getRecentTasksForUser(numTasksToQuery,
ActivityManager.RECENT_IGNORE_UNAVAILABLE |
- ActivityManager.RECENT_INCLUDE_PROFILES, userId);
+ ActivityManager.RECENT_INCLUDE_PROFILES |
+ ActivityManager.RECENT_WITH_EXCLUDED, userId);
+ boolean isFirstValidTask = true;
+ Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
+ while (iter.hasNext()) {
+ ActivityManager.RecentTaskInfo t = iter.next();
+
+ // NOTE: The order of these checks happens in the expected order of the traversal of the
+ // tasks
+
+ // Skip tasks from this Recents package
+ if (t.baseIntent.getComponent().getPackageName().equals(mRecentsPackage)) {
+ iter.remove();
+ continue;
+ }
+ // Check the first non-recents task, include this task even if it is marked as excluded
+ // from recents. In other words, only remove excluded tasks if it is not the first task
+ boolean isExcluded = (t.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
+ == Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+ if (isExcluded && !isFirstValidTask) {
+ iter.remove();
+ continue;
+ }
+ isFirstValidTask = false;
+ // Skip tasks in the home stack
+ if (isInHomeStack(t.persistentId)) {
+ iter.remove();
+ continue;
+ }
+ }
+
+ return tasks.subList(0, Math.min(tasks.size(), numLatestTasks));
}
/** Returns a list of the running tasks */
@@ -165,11 +199,12 @@ public class SystemServicesProxy {
}
/** Removes the task and kills the process */
- public void removeTask(int taskId) {
+ public void removeTask(int taskId, boolean isDocument) {
if (mAm == null) return;
if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
- mAm.removeTask(taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
+ // Remove the task, and only kill the process if it is not a document
+ mAm.removeTask(taskId, isDocument ? 0 : ActivityManager.REMOVE_TASK_KILL_PROCESS);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
index b602f84..46e6ee9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
@@ -18,6 +18,7 @@ package com.android.systemui.recents;
import android.graphics.Color;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
/* Common code */
public class Utilities {
@@ -54,12 +55,15 @@ public class Utilities {
0.0722f * Color.blue(color));
}
- /** Returns the ideal text color to draw on top of a specified background color. */
- public static int getIdealTextColorForBackgroundColor(int color) {
- RecentsConfiguration configuration = RecentsConfiguration.getInstance();
+ /** Returns the ideal color to draw on top of a specified background color. */
+ public static int getIdealColorForBackgroundColor(int color, int lightRes, int darkRes) {
int greyscale = colorToGreyscale(color);
- return (greyscale < 128) ? configuration.taskBarViewLightTextColor :
- configuration.taskBarViewDarkTextColor;
-
+ return (greyscale < 128) ? lightRes : darkRes;
+ }
+ /** Returns the ideal drawable to draw on top of a specified background color. */
+ public static Drawable getIdealResourceForBackgroundColor(int color, Drawable lightRes,
+ Drawable darkRes) {
+ int greyscale = colorToGreyscale(color);
+ return (greyscale < 128) ? lightRes : darkRes;
}
}
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 8168619..a6d7e67 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -346,7 +346,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
RecentsTaskLoader.getInstance().getSystemServicesProxy()
.moveTaskToFront(task.key.id, opts);
} else {
- // Launch the activity with the desired animation
+ // Launch the activity anew with the desired animation
Intent i = new Intent(task.key.baseIntent);
i.setFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
| Intent.FLAG_ACTIVITY_TASK_ON_HOME
@@ -361,6 +361,9 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
} catch (ActivityNotFoundException anfe) {
Console.logError(getContext(), "Could not start Activity");
}
+
+ // And clean up the old task
+ onTaskRemoved(task);
}
Console.logTraceTime(Constants.Log.App.TimeRecentsLaunchTask,
@@ -390,6 +393,22 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
.addNextIntentWithParentStack(intent).startActivities();
}
+ @Override
+ public void onTaskRemoved(Task t) {
+ // Remove any stored data from the loader. We currently don't bother notifying the views
+ // that the data has been unloaded because at the point we call onTaskRemoved(), the views
+ // either don't need to be updated, or have already been removed.
+ RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+ loader.deleteTaskData(t, false);
+
+ // Remove the old task from activity manager
+ int flags = t.key.baseIntent.getFlags();
+ boolean isDocument = (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) ==
+ Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
+ RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(t.key.id,
+ isDocument);
+ }
+
/**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
index c6cb812..07caa1b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -16,7 +16,10 @@
package com.android.systemui.recents.views;
+import android.animation.ValueAnimator;
import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -32,9 +35,13 @@ import com.android.systemui.recents.model.Task;
class TaskBarView extends FrameLayout {
Task mTask;
+ ImageView mDismissButton;
ImageView mApplicationIcon;
TextView mActivityDescription;
+ Drawable mLightDismissDrawable;
+ Drawable mDarkDismissDrawable;
+
public TaskBarView(Context context) {
this(context, null);
}
@@ -49,6 +56,9 @@ class TaskBarView extends FrameLayout {
public TaskBarView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ Resources res = context.getResources();
+ mLightDismissDrawable = res.getDrawable(R.drawable.recents_dismiss_light);
+ mDarkDismissDrawable = res.getDrawable(R.drawable.recents_dismiss_dark);
}
@Override
@@ -56,6 +66,28 @@ class TaskBarView extends FrameLayout {
// Initialize the icon and description views
mApplicationIcon = (ImageView) findViewById(R.id.application_icon);
mActivityDescription = (TextView) findViewById(R.id.activity_description);
+ mDismissButton = (ImageView) findViewById(R.id.dismiss_task);
+ }
+
+ /** Synchronizes this bar view's properties with the task's transform */
+ void updateViewPropertiesToTaskTransform(TaskViewTransform animateFromTransform,
+ TaskViewTransform toTransform, int duration) {
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ if (duration > 0) {
+ if (animateFromTransform != null) {
+ mDismissButton.setAlpha(animateFromTransform.dismissAlpha);
+ }
+ mDismissButton.animate()
+ .alpha(toTransform.dismissAlpha)
+ .setStartDelay(0)
+ .setDuration(duration)
+ .setInterpolator(config.defaultBezierInterpolator)
+ .withLayer()
+ .start();
+ } else {
+ mDismissButton.setAlpha(toTransform.dismissAlpha);
+ }
+ mDismissButton.invalidate();
}
/** Binds the bar view to the task */
@@ -74,7 +106,10 @@ class TaskBarView extends FrameLayout {
int tint = t.colorPrimary;
if (Constants.DebugFlags.App.EnableTaskBarThemeColors && tint != 0) {
setBackgroundColor(tint);
- mActivityDescription.setTextColor(Utilities.getIdealTextColorForBackgroundColor(tint));
+ mActivityDescription.setTextColor(Utilities.getIdealColorForBackgroundColor(tint,
+ configuration.taskBarViewLightTextColor, configuration.taskBarViewDarkTextColor));
+ mDismissButton.setImageDrawable(Utilities.getIdealResourceForBackgroundColor(tint,
+ mLightDismissDrawable, mDarkDismissDrawable));
} else {
setBackgroundColor(configuration.taskBarViewDefaultBackgroundColor);
mActivityDescription.setTextColor(configuration.taskBarViewDefaultTextColor);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
index c6c29a6..f1c362a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
@@ -30,7 +30,6 @@ import android.util.AttributeSet;
import android.widget.Button;
import android.widget.FrameLayout;
import com.android.systemui.R;
-import com.android.systemui.recents.BakedBezierInterpolator;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.Utilities;
@@ -111,7 +110,8 @@ class TaskInfoView extends FrameLayout {
int duration = Utilities.calculateTranslationAnimationDuration((int) mMaxClipRadius);
mCircularClipAnimator = ObjectAnimator.ofFloat(this, "circularClipRadius", toRadius);
mCircularClipAnimator.setDuration(duration);
- mCircularClipAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
+ mCircularClipAnimator.setInterpolator(
+ RecentsConfiguration.getInstance().defaultBezierInterpolator);
mCircularClipAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -143,7 +143,7 @@ class TaskInfoView extends FrameLayout {
.scaleX(1f)
.scaleY(1f)
.setDuration(duration)
- .setInterpolator(BakedBezierInterpolator.INSTANCE)
+ .setInterpolator(RecentsConfiguration.getInstance().defaultBezierInterpolator)
.withLayer()
.start();
}
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 ad0f2f82..b64225e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -23,6 +23,7 @@ import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.Region;
@@ -36,7 +37,6 @@ import android.view.ViewParent;
import android.widget.FrameLayout;
import android.widget.OverScroller;
import com.android.systemui.R;
-import com.android.systemui.recents.BakedBezierInterpolator;
import com.android.systemui.recents.Console;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
@@ -60,6 +60,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
interface TaskStackViewCallbacks {
public void onTaskLaunched(TaskStackView stackView, TaskView tv, TaskStack stack, Task t);
public void onTaskAppInfoLaunched(Task t);
+ public void onTaskRemoved(Task t);
}
TaskStack mStack;
@@ -168,6 +169,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
transform.translationY = (int) (boundedT * overlapHeight - scaleYOffset);
}
+ // Set the alphas
+ transform.dismissAlpha = Math.max(-1f, Math.min(0f, t)) + 1f;
+
// Update the rect and visibility
transform.rect.set(mTaskRect);
if (t < -(numPeekCards + 1)) {
@@ -336,7 +340,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
mScrollAnimator.setDuration(Utilities.calculateTranslationAnimationDuration(newScroll -
curScroll, 250));
- mScrollAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
+ mScrollAnimator.setInterpolator(RecentsConfiguration.getInstance().defaultBezierInterpolator);
mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
@@ -1034,6 +1038,15 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
+ @Override
+ public void onTaskDismissed(TaskView tv) {
+ Task task = tv.getTask();
+ // Remove the task from the view
+ mStack.removeTask(task);
+ // Notify the callback that we've removed the task and it can clean up after it
+ mCb.onTaskRemoved(task);
+ }
+
/**** View.OnClickListener Implementation ****/
@Override
@@ -1093,6 +1106,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
@Override
public void onComponentRemoved(Set<ComponentName> cns) {
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
// 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--) {
@@ -1475,17 +1489,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
@Override
public void onChildDismissed(View v) {
TaskView tv = (TaskView) v;
- Task task = tv.getTask();
-
- // Remove the task from the view
- mSv.mStack.removeTask(task);
-
- // Remove any stored data from the loader
- RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
- loader.deleteTaskData(task);
-
- // Remove the task from activity manager
- RecentsTaskLoader.getInstance().getSystemServicesProxy().removeTask(tv.getTask().key.id);
+ mSv.onTaskDismissed(tv);
// Disable HW layers
mSv.decHwLayersRefCount("swipeComplete");
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 b03f389..5fad629 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -31,7 +31,6 @@ import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.widget.FrameLayout;
import com.android.systemui.R;
-import com.android.systemui.recents.BakedBezierInterpolator;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.model.Task;
@@ -46,6 +45,7 @@ public class TaskView extends FrameLayout implements View.OnClickListener,
public void onTaskInfoPanelShown(TaskView tv);
public void onTaskInfoPanelHidden(TaskView tv);
public void onTaskAppInfoClicked(TaskView tv);
+ public void onTaskDismissed(TaskView tv);
// public void onTaskViewReboundToTask(TaskView tv, Task t);
}
@@ -143,6 +143,10 @@ public class TaskView extends FrameLayout implements View.OnClickListener,
int minZ = config.taskViewTranslationZMinPx;
int incZ = config.taskViewTranslationZIncrementPx;
+ // Update the bar view
+ mBarView.updateViewPropertiesToTaskTransform(animateFromTransform, toTransform, duration);
+
+ // Update this task view
if (duration > 0) {
if (animateFromTransform != null) {
setTranslationY(animateFromTransform.translationY);
@@ -161,7 +165,7 @@ public class TaskView extends FrameLayout implements View.OnClickListener,
.scaleY(toTransform.scale)
.alpha(toTransform.alpha)
.setDuration(duration)
- .setInterpolator(BakedBezierInterpolator.INSTANCE)
+ .setInterpolator(config.defaultBezierInterpolator)
.withLayer()
.setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
@@ -221,8 +225,8 @@ public class TaskView extends FrameLayout implements View.OnClickListener,
mBarView.setAlpha(0f);
mBarView.animate()
.alpha(1f)
- .setStartDelay(235)
- .setInterpolator(BakedBezierInterpolator.INSTANCE)
+ .setStartDelay(250)
+ .setInterpolator(config.defaultBezierInterpolator)
.setDuration(config.taskBarEnterAnimDuration)
.withLayer()
.start();
@@ -234,7 +238,7 @@ public class TaskView extends FrameLayout implements View.OnClickListener,
mBarView.animate()
.alpha(0f)
.setStartDelay(0)
- .setInterpolator(BakedBezierInterpolator.INSTANCE)
+ .setInterpolator(config.defaultBezierInterpolator)
.setDuration(config.taskBarExitAnimDuration)
.withLayer()
.withEndAction(new Runnable() {
@@ -252,7 +256,7 @@ public class TaskView extends FrameLayout implements View.OnClickListener,
animate().translationX(config.taskViewRemoveAnimTranslationXPx)
.alpha(0f)
.setStartDelay(0)
- .setInterpolator(BakedBezierInterpolator.INSTANCE)
+ .setInterpolator(config.defaultBezierInterpolator)
.setDuration(config.taskViewRemoveAnimDuration)
.withLayer()
.withEndAction(new Runnable() {
@@ -310,7 +314,7 @@ public class TaskView extends FrameLayout implements View.OnClickListener,
mInfoView.animate()
.alpha(0f)
.setDuration(config.taskViewInfoPaneAnimDuration)
- .setInterpolator(BakedBezierInterpolator.INSTANCE)
+ .setInterpolator(config.defaultBezierInterpolator)
.withLayer()
.withEndAction(new Runnable() {
@Override
@@ -380,6 +384,7 @@ public class TaskView extends FrameLayout implements View.OnClickListener,
mInfoView.rebindToTask(mTask, reloadingTaskData);
// Rebind any listeners
mBarView.mApplicationIcon.setOnClickListener(this);
+ mBarView.mDismissButton.setOnClickListener(this);
mInfoView.mAppInfoButton.setOnClickListener(this);
}
mTaskDataLoaded = true;
@@ -405,6 +410,15 @@ public class TaskView extends FrameLayout implements View.OnClickListener,
hideInfoPane();
} else if (v == mBarView.mApplicationIcon) {
mCb.onTaskIconClicked(this);
+ } else if (v == mBarView.mDismissButton) {
+ // Animate out the view and call the callback
+ final TaskView tv = this;
+ animateRemoval(new Runnable() {
+ @Override
+ public void run() {
+ mCb.onTaskDismissed(tv);
+ }
+ });
} else if (v == mInfoView.mAppInfoButton) {
mCb.onTaskAppInfoClicked(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
index 0748bbb..e6391a8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -24,6 +24,7 @@ public class TaskViewTransform {
public int translationY = 0;
public float scale = 1f;
public float alpha = 1f;
+ public float dismissAlpha = 1f;
public boolean visible = false;
public Rect rect = new Rect();
float t;
@@ -36,6 +37,7 @@ public class TaskViewTransform {
translationY = o.translationY;
scale = o.scale;
alpha = o.alpha;
+ dismissAlpha = o.dismissAlpha;
visible = o.visible;
rect.set(o.rect);
t = o.t;
@@ -44,6 +46,6 @@ public class TaskViewTransform {
@Override
public String toString() {
return "TaskViewTransform y: " + translationY + " scale: " + scale + " alpha: " + alpha +
- " visible: " + visible + " rect: " + rect;
+ " visible: " + visible + " rect: " + rect + " dismissAlpha: " + dismissAlpha;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 327e715..1747e6e 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -119,7 +119,6 @@ public class BrightnessController implements ToggleSlider.Listener {
}
};
mBrightnessObserver = new BrightnessObserver(mHandler);
- mBrightnessObserver.startObserving();
PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mMinimumBacklight = pm.getMinimumScreenBrightnessSetting();
@@ -128,13 +127,6 @@ public class BrightnessController implements ToggleSlider.Listener {
mAutomaticAvailable = context.getResources().getBoolean(
com.android.internal.R.bool.config_automatic_brightness_available);
mPower = IPowerManager.Stub.asInterface(ServiceManager.getService("power"));
-
- // Update the slider and mode before attaching the listener so we don't receive the
- // onChanged notifications for the initial values.
- updateMode();
- updateSlider();
-
- control.setOnChangedListener(this);
}
public void addStateChangedCallback(BrightnessStateChangeCallback cb) {
@@ -150,11 +142,24 @@ public class BrightnessController implements ToggleSlider.Listener {
// Do nothing
}
+ public void registerCallbacks() {
+ mBrightnessObserver.startObserving();
+ mUserTracker.startTracking();
+
+ // Update the slider and mode before attaching the listener so we don't receive the
+ // onChanged notifications for the initial values.
+ updateMode();
+ updateSlider();
+
+ mControl.setOnChangedListener(this);
+ }
+
/** Unregister all call backs, both to and from the controller */
public void unregisterCallbacks() {
mBrightnessObserver.stopObserving();
mChangeCallbacks.clear();
mUserTracker.stopTracking();
+ mControl.setOnChangedListener(null);
}
public void onChanged(ToggleSlider view, boolean tracking, boolean automatic, int value) {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
index bd5e5e8..27881c4 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
@@ -92,6 +92,7 @@ public class BrightnessDialog extends Dialog implements
mBrightnessController = new BrightnessController(getContext(),
(ImageView) findViewById(R.id.brightness_icon),
(ToggleSlider) findViewById(R.id.brightness_slider));
+ mBrightnessController.registerCallbacks();
dismissBrightnessDialog(mBrightnessDialogLongTimeout);
mBrightnessController.addStateChangedCallback(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java b/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java
index 036bd4f..f8ff616 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java
@@ -29,9 +29,6 @@ public abstract class CurrentUserTracker extends BroadcastReceiver {
private int mCurrentUserId;
public CurrentUserTracker(Context context) {
- IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
- context.registerReceiver(this, filter);
- mCurrentUserId = ActivityManager.getCurrentUser();
mContext = context;
}
@@ -50,6 +47,12 @@ public abstract class CurrentUserTracker extends BroadcastReceiver {
}
}
+ public void startTracking() {
+ mCurrentUserId = ActivityManager.getCurrentUser();
+ IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
+ mContext.registerReceiver(this, filter);
+ }
+
public void stopTracking() {
mContext.unregisterReceiver(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
index 7d38058..4b78072 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java
@@ -62,7 +62,6 @@ public class ToggleSlider extends RelativeLayout {
mToggle = (CompoundButton) findViewById(R.id.toggle);
mToggle.setOnCheckedChangeListener(mCheckListener);
- mToggle.setBackground(res.getDrawable(R.drawable.status_bar_toggle_button));
mSlider = (SeekBar) findViewById(R.id.slider);
mSlider.setOnSeekBarChangeListener(mSeekListener);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index ecefc39..898f06e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1029,6 +1029,9 @@ public abstract class BaseStatusBar extends SystemUI implements
}
protected void addNotificationViews(NotificationData.Entry entry) {
+ if (entry == null) {
+ return;
+ }
// Add the expanded view and icon.
int pos = mNotificationData.add(entry);
if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 281bd2d..4bd0e1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -112,7 +112,7 @@ public abstract class ExpandableView extends FrameLayout {
* @return The desired notification height.
*/
public int getIntrinsicHeight() {
- return mActualHeight;
+ return getHeight();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
index 864c597..451c5c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
@@ -34,21 +34,6 @@ public class NotificationOverflowContainer extends ActivatableNotificationView {
}
@Override
- public void setActualHeight(int currentHeight, boolean notifyListeners) {
- // noop
- }
-
- @Override
- public int getActualHeight() {
- return getHeight();
- }
-
- @Override
- public void setClipTopAmount(int clipTopAmount) {
- // noop
- }
-
- @Override
protected void onFinishInflate() {
super.onFinishInflate();
mIconsView = (NotificationOverflowIconsView) findViewById(R.id.overflow_icons_view);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
new file mode 100644
index 0000000..c26f15e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -0,0 +1,90 @@
+/*
+ * 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.statusbar.phone;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Canvas;
+import android.graphics.Path;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.ContactsContract;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+
+import com.android.systemui.R;
+import com.android.systemui.settings.UserSwitcherHostView;
+import com.android.systemui.statusbar.policy.UserInfoController;
+
+/**
+ * Image button for the multi user switcher.
+ */
+public class MultiUserSwitch extends ImageButton implements View.OnClickListener,
+ UserInfoController.OnUserInfoChangedListener {
+
+ private ViewGroup mOverlayParent;
+
+ public MultiUserSwitch(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ setOnClickListener(this);
+ }
+
+ public void setOverlayParent(ViewGroup parent) {
+ mOverlayParent = parent;
+ }
+
+ @Override
+ public void onClick(View v) {
+ final UserManager um = UserManager.get(getContext());
+ if (um.isUserSwitcherEnabled()) {
+ final UserSwitcherHostView switcher =
+ (UserSwitcherHostView) LayoutInflater.from(getContext()).inflate(
+ R.layout.user_switcher_host, mOverlayParent, false);
+ switcher.setFinishRunnable(new Runnable() {
+ @Override
+ public void run() {
+ mOverlayParent.removeView(switcher);
+ }
+ });
+ switcher.refreshUsers();
+ mOverlayParent.addView(switcher);
+ } else {
+ Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
+ getContext(), v, ContactsContract.Profile.CONTENT_URI,
+ ContactsContract.QuickContact.MODE_LARGE, null);
+ getContext().startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ }
+ }
+
+ public void setUserInfoController(UserInfoController userInfoController) {
+ userInfoController.addListener(this);
+ }
+
+ @Override
+ public void onUserInfoChanged(String name, Drawable picture) {
+ setImageDrawable(picture);
+ }
+}
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 f63ba9c..6132ed2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -24,9 +24,11 @@ import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
+import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
+import android.widget.LinearLayout;
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableView;
@@ -56,10 +58,18 @@ public class NotificationPanelView extends PanelView implements
private int mTrackingPointer;
private VelocityTracker mVelocityTracker;
private boolean mTracking;
+
+ /**
+ * Whether we are currently handling a motion gesture in #onInterceptTouchEvent, but haven't
+ * intercepted yet.
+ */
+ private boolean mIntercepting;
private boolean mQsExpanded;
private float mInitialHeightOnTouch;
private float mInitialTouchX;
private float mInitialTouchY;
+ private float mLastTouchX;
+ private float mLastTouchY;
private float mQsExpansionHeight;
private int mQsMinExpansionHeight;
private int mQsMaxExpansionHeight;
@@ -93,6 +103,7 @@ public class NotificationPanelView extends PanelView implements
super.onFinishInflate();
mHeader = (StatusBarHeaderView) findViewById(R.id.header);
mHeader.getBackgroundView().setOnClickListener(this);
+ mHeader.setOverlayParent(this);
mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
mStackScrollerContainer = findViewById(R.id.notification_container_parent);
mQsContainer = (QuickSettingsContainerView) findViewById(R.id.quick_settings_container);
@@ -144,7 +155,6 @@ public class NotificationPanelView extends PanelView implements
public void setQsExpansionEnabled(boolean qsExpansionEnabled) {
mQsExpansionEnabled = qsExpansionEnabled;
- mHeader.setExpansionEnabled(qsExpansionEnabled);
}
public void closeQs() {
@@ -193,6 +203,7 @@ public class NotificationPanelView extends PanelView implements
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
+ mIntercepting = true;
mInitialTouchY = y;
mInitialTouchX = x;
initVelocityTracker();
@@ -215,6 +226,16 @@ public class NotificationPanelView extends PanelView implements
case MotionEvent.ACTION_MOVE:
final float h = y - mInitialTouchY;
trackMovement(event);
+ if (mTracking) {
+
+ // Already tracking because onOverscrolled was called. We need to update here
+ // so we don't stop for a frame until the next touch event gets handled in
+ // onTouchEvent.
+ setQsExpansion(h + mInitialHeightOnTouch);
+ trackMovement(event);
+ mIntercepting = false;
+ return true;
+ }
if (Math.abs(h) > mTouchSlop && Math.abs(h) > Math.abs(x - mInitialTouchX)
&& shouldIntercept(mInitialTouchX, mInitialTouchY, h)) {
onQsExpansionStarted();
@@ -222,14 +243,29 @@ public class NotificationPanelView extends PanelView implements
mInitialTouchY = y;
mInitialTouchX = x;
mTracking = true;
+ mIntercepting = false;
return true;
}
break;
+
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ mIntercepting = false;
+ break;
}
return !mQsExpanded && super.onInterceptTouchEvent(event);
}
@Override
+ public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+
+ // Block request so we can still intercept the scrolling when QS is expanded.
+ if (!mQsExpanded) {
+ super.requestDisallowInterceptTouchEvent(disallowIntercept);
+ }
+ }
+
+ @Override
public boolean onTouchEvent(MotionEvent event) {
// TODO: Handle doublefinger swipe to notifications again. Look at history for a reference
// implementation.
@@ -297,11 +333,26 @@ public class NotificationPanelView extends PanelView implements
return mQsExpanded || super.onTouchEvent(event);
}
+ @Override
+ public void onOverscrolled(int amount) {
+ if (mIntercepting) {
+ onQsExpansionStarted(amount);
+ mInitialHeightOnTouch = mQsExpansionHeight;
+ mInitialTouchY = mLastTouchY;
+ mInitialTouchX = mLastTouchX;
+ mTracking = true;
+ }
+ }
+
private void onQsExpansionStarted() {
+ onQsExpansionStarted(0);
+ }
+
+ private void onQsExpansionStarted(int overscrollAmount) {
cancelAnimation();
// Reset scroll position and apply that position to the expanded height.
- float height = mQsExpansionHeight - mScrollView.getScrollY();
+ float height = mQsExpansionHeight - mScrollView.getScrollY() - overscrollAmount;
mScrollView.scrollTo(0, 0);
setQsExpansion(height);
}
@@ -359,6 +410,8 @@ public class NotificationPanelView extends PanelView implements
private void trackMovement(MotionEvent event) {
if (mVelocityTracker != null) mVelocityTracker.addMovement(event);
+ mLastTouchX = event.getX();
+ mLastTouchY = event.getY();
}
private void initVelocityTracker() {
@@ -412,11 +465,8 @@ public class NotificationPanelView extends PanelView implements
if (!mQsExpansionEnabled) {
return false;
}
- View headerView = mStatusBar.getBarState() == StatusBarState.KEYGUARD && !mQsExpanded
- ? mKeyguardStatusView
- : mHeader;
- boolean onHeader = x >= headerView.getLeft() && x <= headerView.getRight()
- && y >= headerView.getTop() && y <= headerView.getBottom();
+ boolean onHeader = x >= mHeader.getLeft() && x <= mHeader.getRight()
+ && y >= mHeader.getTop() && y <= mHeader.getBottom();
if (mQsExpanded) {
return onHeader || (mScrollView.isScrolledToBottom() && yDiff < 0);
} else {
@@ -425,6 +475,35 @@ public class NotificationPanelView extends PanelView implements
}
@Override
+ public void setVisibility(int visibility) {
+ int oldVisibility = getVisibility();
+ super.setVisibility(visibility);
+ if (visibility != oldVisibility) {
+ reparentStatusIcons(visibility == VISIBLE);
+ }
+ }
+
+ /**
+ * When the notification panel gets expanded, we need to move the status icons in the header
+ * card.
+ */
+ private void reparentStatusIcons(boolean toHeader) {
+ if (mStatusBar == null) {
+ return;
+ }
+ LinearLayout systemIcons = mStatusBar.getSystemIcons();
+ if (systemIcons.getParent() != null) {
+ ((ViewGroup) systemIcons.getParent()).removeView(systemIcons);
+ }
+ if (toHeader) {
+ mHeader.attachSystemIcons(systemIcons);
+ } else {
+ mHeader.onSystemIconsDetached();
+ mStatusBar.reattachSystemIcons();
+ }
+ }
+
+ @Override
protected boolean isScrolledToBottom() {
if (!isInSettings()) {
return mNotificationStackScroller.isScrolledToBottom();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
index 46484f3..ba0b66e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java
@@ -27,6 +27,7 @@ import android.widget.ScrollView;
public class ObservableScrollView extends ScrollView {
private Listener mListener;
+ private int mLastOverscrollAmount;
public ObservableScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -58,7 +59,25 @@ public class ObservableScrollView extends ScrollView {
}
}
+ @Override
+ protected boolean overScrollBy(int deltaX, int deltaY, int scrollX, int scrollY,
+ int scrollRangeX, int scrollRangeY, int maxOverScrollX, int maxOverScrollY,
+ boolean isTouchEvent) {
+ mLastOverscrollAmount = Math.max(0, scrollY + deltaY - getMaxScrollY());
+ return super.overScrollBy(deltaX, deltaY, scrollX, scrollY, scrollRangeX, scrollRangeY,
+ maxOverScrollX, maxOverScrollY, isTouchEvent);
+ }
+
+ @Override
+ protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
+ super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
+ if (mListener != null && mLastOverscrollAmount > 0) {
+ mListener.onOverscrolled(mLastOverscrollAmount);
+ }
+ }
+
public interface Listener {
void onScrollChanged();
+ void onOverscrolled(int amount);
}
}
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 92eee4e..4d09d6a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -29,7 +29,6 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCE
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
@@ -112,6 +111,7 @@ import com.android.systemui.statusbar.policy.HeadsUpNotificationView;
import com.android.systemui.statusbar.policy.LocationController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
import com.android.systemui.statusbar.stack.StackScrollState.ViewState;
@@ -185,6 +185,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
LocationController mLocationController;
NetworkController mNetworkController;
RotationLockController mRotationLockController;
+ UserInfoController mUserInfoController;
int mNaturalBarHeight = -1;
int mIconSize = -1;
@@ -205,6 +206,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// right-hand icons
LinearLayout mSystemIconArea;
+ LinearLayout mSystemIcons;
// left-hand icons
LinearLayout mStatusIcons;
@@ -221,7 +223,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
int mNotificationPanelGravity;
int mNotificationPanelMarginBottomPx;
float mNotificationPanelMinHeightFrac;
- boolean mNotificationPanelIsFullScreenWidth;
TextView mNotificationPanelDebugText;
// settings
@@ -230,7 +231,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
QuickSettingsContainerView mSettingsContainer;
// top bar
- View mNotificationPanelHeader;
+ StatusBarHeaderView mHeader;
View mKeyguardStatusView;
KeyguardBottomAreaView mKeyguardBottomArea;
boolean mLeaveOpenOnKeyguardHide;
@@ -240,8 +241,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
String mKeyguardHotwordPhrase = "";
int mKeyguardMaxNotificationCount;
View mDateTimeView;
- View mClearButton;
- ImageView mHeaderFlipper;
// carrier/wifi label
private TextView mCarrierLabel;
@@ -249,7 +248,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private int mCarrierLabelHeight;
private TextView mEmergencyCallLabel;
private int mStatusBarHeaderHeight;
- private View mKeyguardCarrierLabel;
private boolean mShowCarrierInPanel = false;
@@ -554,8 +552,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mNotificationPanel = (NotificationPanelView) mStatusBarWindow.findViewById(
R.id.notification_panel);
mNotificationPanel.setStatusBar(this);
- mNotificationPanelIsFullScreenWidth =
- (mNotificationPanel.getLayoutParams().width == ViewGroup.LayoutParams.MATCH_PARENT);
// make the header non-responsive to clicks
mNotificationPanel.findViewById(R.id.header).setOnTouchListener(
@@ -609,6 +605,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mPixelFormat = PixelFormat.OPAQUE;
mSystemIconArea = (LinearLayout) mStatusBarView.findViewById(R.id.system_icon_area);
+ mSystemIcons = (LinearLayout) mStatusBarView.findViewById(R.id.system_icons);
mStatusIcons = (LinearLayout)mStatusBarView.findViewById(R.id.statusIcons);
mNotificationIcons = (IconMerger)mStatusBarView.findViewById(R.id.notificationIcons);
mMoreIcon = mStatusBarView.findViewById(R.id.moreIcon);
@@ -627,39 +624,30 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
(NotificationOverflowContainer) LayoutInflater.from(mContext).inflate(
R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false);
mKeyguardIconOverflowContainer.setOnActivatedListener(this);
- mKeyguardCarrierLabel = mStatusBarWindow.findViewById(R.id.keyguard_carrier_text);
mKeyguardIconOverflowContainer.setOnClickListener(mOverflowClickListener);
mStackScroller.addView(mKeyguardIconOverflowContainer);
mExpandedContents = mStackScroller;
- mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header);
+ mHeader = (StatusBarHeaderView) mStatusBarWindow.findViewById(R.id.header);
+ mHeader.setActivityStarter(this);
mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
mKeyguardBottomArea =
(KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
mKeyguardBottomArea.setActivityStarter(this);
mKeyguardIndicationTextView = (KeyguardIndicationTextView) mStatusBarWindow.findViewById(
R.id.keyguard_indication_text);
- mClearButton = mStatusBarWindow.findViewById(R.id.clear_all_button);
- mClearButton.setOnClickListener(mClearButtonListener);
- mClearButton.setAlpha(0f);
- mClearButton.setVisibility(View.INVISIBLE);
- mClearButton.setEnabled(false);
mDateView = (DateView)mStatusBarWindow.findViewById(R.id.date);
- mDateTimeView = mNotificationPanelHeader.findViewById(R.id.datetime);
+ mDateTimeView = mHeader.findViewById(R.id.datetime);
if (mDateTimeView != null) {
mDateTimeView.setOnClickListener(mClockClickListener);
mDateTimeView.setEnabled(true);
}
- mHeaderFlipper = (ImageView) mStatusBarWindow.findViewById(R.id.header_flipper);
-
- if (!mNotificationPanelIsFullScreenWidth) {
- mNotificationPanel.setSystemUiVisibility(
- View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS |
- View.STATUS_BAR_DISABLE_CLOCK);
- }
+ mNotificationPanel.setSystemUiVisibility(
+ View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS |
+ View.STATUS_BAR_DISABLE_CLOCK);
mTicker = new MyTicker(context, mStatusBarView);
@@ -680,6 +668,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
|| QuickSettings.DEBUG_GONE_TILES) {
mRotationLockController = new RotationLockController(mContext);
}
+ mUserInfoController = new UserInfoController(mContext);
final SignalClusterView signalCluster =
(SignalClusterView)mStatusBarView.findViewById(R.id.signal_cluster);
@@ -734,11 +723,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mFlipSettingsView = mSettingsContainer;
if (mSettingsContainer != null) {
mQS = new QuickSettings(mContext, mSettingsContainer);
- if (!mNotificationPanelIsFullScreenWidth) {
- mSettingsContainer.setSystemUiVisibility(
- View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS
- | View.STATUS_BAR_DISABLE_SYSTEM_INFO);
- }
mQS.setService(this);
mQS.setBar(mStatusBarView);
mQS.setup(mNetworkController, mBluetoothController, mBatteryController,
@@ -747,6 +731,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mQS = null; // fly away, be free
}
+ // User info. Trigger first load.
+ mHeader.setUserInfoController(mUserInfoController);
+ mUserInfoController.reloadUserInfo();
+
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mBroadcastReceiver.onReceive(mContext,
new Intent(pm.isScreenOn() ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF));
@@ -1118,19 +1106,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (mNavigationBarView != null) {
mNavigationBarView.setLayoutDirection(layoutDirection);
}
-
- if (mClearButton != null && mClearButton instanceof ImageView) {
- // Force asset reloading
- ((ImageView)mClearButton).setImageDrawable(null);
- ((ImageView)mClearButton).setImageResource(R.drawable.ic_notify_clear);
- }
-
- if (mHeaderFlipper != null) {
- // Force asset reloading
- mHeaderFlipper.setImageDrawable(null);
- mHeaderFlipper.setImageResource(R.drawable.ic_notify_quicksettings);
- }
-
refreshAllStatusBarIcons();
}
@@ -1301,38 +1276,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
+ " any=" + any + " clearable=" + clearable);
}
- if (mFlipSettingsView != null
- && mFlipSettingsView.getVisibility() == View.VISIBLE
- && mStackScroller.getVisibility() != View.VISIBLE) {
- // the flip settings panel is unequivocally showing; we should not be shown
- mClearButton.setVisibility(View.INVISIBLE);
- } else if (mClearButton.isShown()) {
- if (clearable != (mClearButton.getAlpha() == 1.0f)) {
- ObjectAnimator clearAnimation = ObjectAnimator.ofFloat(
- mClearButton, "alpha", clearable ? 1.0f : 0.0f).setDuration(250);
- clearAnimation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (mClearButton.getAlpha() <= 0.0f) {
- mClearButton.setVisibility(View.INVISIBLE);
- }
- }
-
- @Override
- public void onAnimationStart(Animator animation) {
- if (mClearButton.getAlpha() <= 0.0f) {
- mClearButton.setVisibility(View.VISIBLE);
- }
- }
- });
- clearAnimation.start();
- }
- } else {
- mClearButton.setAlpha(clearable ? 1.0f : 0.0f);
- mClearButton.setVisibility(clearable ? View.VISIBLE : View.INVISIBLE);
- }
- mClearButton.setEnabled(clearable);
-
final View nlo = mStatusBarView.findViewById(R.id.notification_lights_out);
final boolean showDot = (any&&!areLightsOn());
if (showDot != (nlo.getAlpha() == 1.0f)) {
@@ -1917,13 +1860,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private void checkBarModes() {
if (mDemoMode) return;
- int sbMode = mStatusBarMode;
- if (panelsEnabled() && (mInteractingWindows & StatusBarManager.WINDOW_STATUS_BAR) != 0
- && mState != StatusBarState.KEYGUARD) {
- // if panels are expandable, force the status bar opaque on any interaction
- sbMode = MODE_OPAQUE;
- }
- checkBarMode(sbMode, mStatusBarWindowState, mStatusBarView.getBarTransitions());
+ checkBarMode(mStatusBarMode, mStatusBarWindowState, mStatusBarView.getBarTransitions());
if (mNavigationBarView != null) {
checkBarMode(mNavigationBarMode,
mNavigationBarWindowState, mNavigationBarView.getBarTransitions());
@@ -2449,10 +2386,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
final Context context = mContext;
final Resources res = context.getResources();
- if (mClearButton instanceof TextView) {
- ((TextView)mClearButton).setText(context.getText(R.string.status_bar_clear_all_button));
- }
-
// Update the QuickSettings container
if (mQS != null) mQS.updateResources();
@@ -2774,20 +2707,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardBottomArea.setVisibility(View.VISIBLE);
mKeyguardIndicationTextView.setVisibility(View.VISIBLE);
mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase);
- mKeyguardCarrierLabel.setVisibility(View.VISIBLE);
- mNotificationPanelHeader.setVisibility(View.GONE);
mNotificationPanel.closeQs();
- mSettingsContainer.setKeyguardShowing(true);
} else {
mKeyguardStatusView.setVisibility(View.GONE);
mKeyguardBottomArea.setVisibility(View.GONE);
mKeyguardIndicationTextView.setVisibility(View.GONE);
- mKeyguardCarrierLabel.setVisibility(View.GONE);
- mNotificationPanelHeader.setVisibility(View.VISIBLE);
-
- mSettingsContainer.setKeyguardShowing(false);
}
+ mSettingsContainer.setKeyguardShowing(mState == StatusBarState.KEYGUARD);
+ mHeader.setKeyguardShowing(mState == StatusBarState.KEYGUARD);
updateStackScrollerState();
updatePublicMode();
@@ -2943,4 +2871,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
public ViewGroup getQuickSettingsOverlayParent() {
return mNotificationPanel;
}
+
+ public LinearLayout getSystemIcons() {
+ return mSystemIcons;
+ }
+
+ /**
+ * Reattaches the system icons to its normal parent in collapsed status bar.
+ */
+ public void reattachSystemIcons() {
+ mSystemIconArea.addView(mSystemIcons, 0);
+ }
}
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 e6de057..084bfcf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -63,7 +63,7 @@ public class PhoneStatusBarView extends PanelBar {
}
@Override
- public void onAttachedToWindow() {
+ public void onFinishInflate() {
mBarTransitions.init();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index e1ef83a..005b0d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -460,6 +460,7 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
rebindMediaRouterAsCurrentUser();
}
};
+ mUserTracker.startTracking();
mNextAlarmObserver = new NextAlarmObserver(mHandler);
mNextAlarmObserver.startObserving();
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 9d33930..5527473 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -17,25 +17,52 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
+import android.content.Intent;
+import android.graphics.Outline;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import com.android.systemui.R;
+import com.android.systemui.settings.BrightnessController;
+import com.android.systemui.settings.ToggleSlider;
+import com.android.systemui.statusbar.policy.UserInfoController;
/**
* The view to manage the header area in the expanded status bar.
*/
-public class StatusBarHeaderView extends RelativeLayout {
+public class StatusBarHeaderView extends RelativeLayout implements View.OnClickListener {
private boolean mExpanded;
+ private boolean mKeyguardShowing;
+
private View mBackground;
- private View mFlipper;
+ private ViewGroup mSystemIconsContainer;
+ private View mDateTime;
+ private View mKeyguardCarrierText;
+ private MultiUserSwitch mMultiUserSwitch;
+ private View mDate;
+ private View mStatusIcons;
+ private View mSignalCluster;
+ private View mSettingsButton;
+ private View mBrightnessContainer;
private int mCollapsedHeight;
private int mExpandedHeight;
+ private int mKeyguardHeight;
+
+ private int mKeyguardWidth = ViewGroup.LayoutParams.MATCH_PARENT;
+ private int mNormalWidth;
+
+ private ActivityStarter mActivityStarter;
+ private BrightnessController mBrightnessController;
+
+ private final Rect mClipBounds = new Rect();
+ private final Outline mOutline = new Outline();
public StatusBarHeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -45,19 +72,35 @@ public class StatusBarHeaderView extends RelativeLayout {
protected void onFinishInflate() {
super.onFinishInflate();
mBackground = findViewById(R.id.background);
- mFlipper = findViewById(R.id.header_flipper);
+ mSystemIconsContainer = (ViewGroup) findViewById(R.id.system_icons_container);
+ mDateTime = findViewById(R.id.datetime);
+ mKeyguardCarrierText = findViewById(R.id.keyguard_carrier_text);
+ mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
+ mDate = findViewById(R.id.date);
+ mSettingsButton = findViewById(R.id.settings_button);
+ mSettingsButton.setOnClickListener(this);
+ mBrightnessContainer = findViewById(R.id.brightness_container);
+ mBrightnessController = new BrightnessController(getContext(),
+ (ImageView) findViewById(R.id.brightness_icon),
+ (ToggleSlider) findViewById(R.id.brightness_slider));
loadDimens();
}
private void loadDimens() {
- mCollapsedHeight = getResources().getDimensionPixelSize(
- R.dimen.status_bar_header_height);
+ mCollapsedHeight = getResources().getDimensionPixelSize(R.dimen.status_bar_header_height);
mExpandedHeight = getResources().getDimensionPixelSize(
R.dimen.status_bar_header_height_expanded);
+ mKeyguardHeight = getResources().getDimensionPixelSize(
+ R.dimen.status_bar_header_height_keyguard);
+ mNormalWidth = getLayoutParams().width;
+ }
+
+ public void setActivityStarter(ActivityStarter activityStarter) {
+ mActivityStarter = activityStarter;
}
public int getCollapsedHeight() {
- return mCollapsedHeight;
+ return mKeyguardShowing ? mKeyguardHeight : mCollapsedHeight;
}
public int getExpandedHeight() {
@@ -65,16 +108,82 @@ public class StatusBarHeaderView extends RelativeLayout {
}
public void setExpanded(boolean expanded) {
- if (expanded != mExpanded) {
- ViewGroup.LayoutParams lp = getLayoutParams();
- lp.height = expanded ? mExpandedHeight : mCollapsedHeight;
+ boolean changed = expanded != mExpanded;
+ mExpanded = expanded;
+ if (changed) {
+ updateHeights();
+ updateVisibilities();
+ updateSystemIconsLayoutParams();
+ updateBrightnessControllerState();
+ }
+ }
+
+ private void updateHeights() {
+ boolean onKeyguardAndCollapsed = mKeyguardShowing && !mExpanded;
+ int height;
+ if (mExpanded) {
+ height = mExpandedHeight;
+ } else if (onKeyguardAndCollapsed) {
+ height = mKeyguardHeight;
+ } else {
+ height = mCollapsedHeight;
+ }
+ ViewGroup.LayoutParams lp = getLayoutParams();
+ if (lp.height != height) {
+ lp.height = height;
setLayoutParams(lp);
- mExpanded = expanded;
+ }
+ int systemIconsContainerHeight = onKeyguardAndCollapsed ? mKeyguardHeight : mCollapsedHeight;
+ lp = mSystemIconsContainer.getLayoutParams();
+ if (lp.height != systemIconsContainerHeight) {
+ lp.height = systemIconsContainerHeight;
+ mSystemIconsContainer.setLayoutParams(lp);
+ }
+ lp = mMultiUserSwitch.getLayoutParams();
+ if (lp.height != systemIconsContainerHeight) {
+ lp.height = systemIconsContainerHeight;
+ mMultiUserSwitch.setLayoutParams(lp);
}
}
- public void setExpansionEnabled(boolean enabled) {
- mFlipper.setVisibility(enabled ? View.VISIBLE : View.GONE);
+ private void updateWidth() {
+ int width = mKeyguardShowing ? mKeyguardWidth : mNormalWidth;
+ ViewGroup.LayoutParams lp = getLayoutParams();
+ if (width != lp.width) {
+ lp.width = width;
+ setLayoutParams(lp);
+ }
+ }
+
+ private void updateVisibilities() {
+ boolean onKeyguardAndCollapsed = mKeyguardShowing && !mExpanded;
+ mBackground.setVisibility(onKeyguardAndCollapsed ? View.INVISIBLE : View.VISIBLE);
+ mDateTime.setVisibility(onKeyguardAndCollapsed ? View.INVISIBLE : View.VISIBLE);
+ mKeyguardCarrierText.setVisibility(onKeyguardAndCollapsed ? View.VISIBLE : View.GONE);
+ mDate.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
+ mSettingsButton.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
+ mBrightnessContainer.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
+ if (mStatusIcons != null) {
+ mStatusIcons.setVisibility(!mExpanded ? View.VISIBLE : View.GONE);
+ }
+ if (mSignalCluster != null) {
+ mSignalCluster.setVisibility(!mExpanded ? View.VISIBLE : View.GONE);
+ }
+ }
+
+ private void updateSystemIconsLayoutParams() {
+ RelativeLayout.LayoutParams lp = (LayoutParams) mSystemIconsContainer.getLayoutParams();
+ lp.addRule(RelativeLayout.START_OF, mExpanded
+ ? mSettingsButton.getId()
+ : mMultiUserSwitch.getId());
+ }
+
+ private void updateBrightnessControllerState() {
+ if (mExpanded) {
+ mBrightnessController.registerCallbacks();
+ } else {
+ mBrightnessController.unregisterCallbacks();
+ }
}
public void setExpansion(float height) {
@@ -89,9 +198,65 @@ public class StatusBarHeaderView extends RelativeLayout {
} else {
mBackground.setTranslationY(0);
}
+ setClipping(height);
+ }
+
+ private void setClipping(float height) {
+ mClipBounds.set(getPaddingLeft(), 0, getWidth() - getPaddingRight(), (int) height);
+ setClipBounds(mClipBounds);
+ mOutline.setRect(mClipBounds);
+ setOutline(mOutline);
}
public View getBackgroundView() {
return mBackground;
}
+
+ public void attachSystemIcons(LinearLayout systemIcons) {
+ mSystemIconsContainer.addView(systemIcons);
+ mStatusIcons = systemIcons.findViewById(R.id.statusIcons);
+ mSignalCluster = systemIcons.findViewById(R.id.signal_cluster);
+ }
+
+ public void onSystemIconsDetached() {
+ if (mStatusIcons != null) {
+ mStatusIcons.setVisibility(View.VISIBLE);
+ }
+ if (mSignalCluster != null) {
+ mSignalCluster.setVisibility(View.VISIBLE);
+ }
+ mStatusIcons = null;
+ mSignalCluster = null;
+ }
+
+ public void setKeyguardShowing(boolean keyguardShowing) {
+ mKeyguardShowing = keyguardShowing;
+ if (keyguardShowing) {
+ setZ(0);
+ } else {
+ setTranslationZ(0);
+ }
+ updateHeights();
+ updateWidth();
+ updateVisibilities();
+ }
+
+ public void setUserInfoController(UserInfoController userInfoController) {
+ mMultiUserSwitch.setUserInfoController(userInfoController);
+ }
+
+ public void setOverlayParent(ViewGroup parent) {
+ mMultiUserSwitch.setOverlayParent(parent);
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (v == mSettingsButton) {
+ startSettingsActivity();
+ }
+ }
+
+ private void startSettingsActivity() {
+ mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS));
+ }
}
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 f24c1b6..48c54fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -73,8 +73,7 @@ public class StatusBarKeyguardViewManager {
public void show(Bundle options) {
mShowing = true;
mStatusBarWindowManager.setKeyguardShowing(true);
- showBouncerOrKeyguard();
- updateStates();
+ reset();
}
/**
@@ -105,13 +104,15 @@ public class StatusBarKeyguardViewManager {
* Reset the state of the view.
*/
public void reset() {
- if (mOccluded) {
- mPhoneStatusBar.hideKeyguard();
- mBouncer.hide();
- } else {
- showBouncerOrKeyguard();
+ if (mShowing) {
+ if (mOccluded) {
+ mPhoneStatusBar.hideKeyguard();
+ mBouncer.hide();
+ } else {
+ showBouncerOrKeyguard();
+ }
+ updateStates();
}
- updateStates();
}
public void onScreenTurnedOff() {
@@ -121,7 +122,6 @@ public class StatusBarKeyguardViewManager {
public void onScreenTurnedOn(final IKeyguardShowCallback callback) {
mScreenOn = true;
- reset();
if (callback != null) {
callbackAfterDraw(callback);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index a4c9df5..8809d18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -78,9 +78,8 @@ public class StatusBarWindowManager {
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
PixelFormat.TRANSLUCENT);
-
mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
- mLp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
+ mLp.gravity = Gravity.TOP;
mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
mLp.setTitle("StatusBar");
mLp.packageName = mContext.getPackageName();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 8ced1c9..55a0bba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -20,6 +20,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.TypedArray;
import android.os.Bundle;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
@@ -30,6 +31,7 @@ import android.util.AttributeSet;
import android.widget.TextView;
import com.android.systemui.DemoMode;
+import com.android.systemui.R;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -52,7 +54,7 @@ public class Clock extends TextView implements DemoMode {
private static final int AM_PM_STYLE_SMALL = 1;
private static final int AM_PM_STYLE_GONE = 2;
- private static final int AM_PM_STYLE = AM_PM_STYLE_GONE;
+ private final int mAmPmStyle;
public Clock(Context context) {
this(context, null);
@@ -64,6 +66,15 @@ public class Clock extends TextView implements DemoMode {
public Clock(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ TypedArray a = context.getTheme().obtainStyledAttributes(
+ attrs,
+ R.styleable.Clock,
+ 0, 0);
+ try {
+ mAmPmStyle = a.getInt(R.styleable.Clock_amPmStyle, AM_PM_STYLE_GONE);
+ } finally {
+ a.recycle();
+ }
}
@Override
@@ -145,7 +156,7 @@ public class Clock extends TextView implements DemoMode {
* add dummy characters around it to let us find it again after
* formatting and change its size.
*/
- if (AM_PM_STYLE != AM_PM_STYLE_NORMAL) {
+ if (mAmPmStyle != AM_PM_STYLE_NORMAL) {
int a = -1;
boolean quoted = false;
for (int i = 0; i < format.length(); i++) {
@@ -177,15 +188,15 @@ public class Clock extends TextView implements DemoMode {
}
String result = sdf.format(mCalendar.getTime());
- if (AM_PM_STYLE != AM_PM_STYLE_NORMAL) {
+ if (mAmPmStyle != AM_PM_STYLE_NORMAL) {
int magic1 = result.indexOf(MAGIC1);
int magic2 = result.indexOf(MAGIC2);
if (magic1 >= 0 && magic2 > magic1) {
SpannableStringBuilder formatted = new SpannableStringBuilder(result);
- if (AM_PM_STYLE == AM_PM_STYLE_GONE) {
+ if (mAmPmStyle == AM_PM_STYLE_GONE) {
formatted.delete(magic1, magic2+1);
} else {
- if (AM_PM_STYLE == AM_PM_STYLE_SMALL) {
+ if (mAmPmStyle == AM_PM_STYLE_SMALL) {
CharacterStyle style = new RelativeSizeSpan(0.7f);
formatted.setSpan(style, magic1, magic2,
Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
new file mode 100644
index 0000000..173af40
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoController.java
@@ -0,0 +1,215 @@
+/*
+ * 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.statusbar.policy;
+
+import android.app.ActivityManagerNative;
+import android.bluetooth.BluetoothAdapter;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.UserInfo;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.Shader;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
+import android.os.AsyncTask;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.ContactsContract;
+import android.security.KeyChain;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.internal.view.RotationPolicy;
+import com.android.systemui.R;
+
+import java.util.ArrayList;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public final class UserInfoController {
+
+ private static final String TAG = "UserInfoController";
+
+ private final Context mContext;
+ private final ArrayList<OnUserInfoChangedListener> mCallbacks =
+ new ArrayList<OnUserInfoChangedListener>();
+ private AsyncTask<Void, Void, Pair<String, Drawable>> mUserInfoTask;
+
+ private boolean mUseDefaultAvatar;
+ private String mUserName;
+ private Drawable mUserDrawable;
+
+ public UserInfoController(Context context) {
+ mContext = context;
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+ mContext.registerReceiver(mReceiver, filter);
+
+ IntentFilter profileFilter = new IntentFilter();
+ profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED);
+ profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
+ mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter,
+ null, null);
+ }
+
+ public void addListener(OnUserInfoChangedListener callback) {
+ mCallbacks.add(callback);
+ }
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+ reloadUserInfo();
+ } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
+ if (mUseDefaultAvatar) {
+ reloadUserInfo();
+ }
+ }
+ }
+ };
+
+ private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) ||
+ Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
+ try {
+ final int currentUser = ActivityManagerNative.getDefault().getCurrentUser().id;
+ final int changedUser =
+ intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId());
+ if (changedUser == currentUser) {
+ reloadUserInfo();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't get current user id for profile change", e);
+ }
+ }
+ }
+ };
+
+ public void reloadUserInfo() {
+ if (mUserInfoTask != null) {
+ mUserInfoTask.cancel(false);
+ mUserInfoTask = null;
+ }
+ queryForUserInformation();
+ }
+
+ private Bitmap circularClip(Bitmap input) {
+ Bitmap output = Bitmap.createBitmap(input.getWidth(),
+ input.getHeight(), Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(output);
+ final Paint paint = new Paint();
+ paint.setShader(new BitmapShader(input, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
+ paint.setAntiAlias(true);
+ canvas.drawCircle(input.getWidth() / 2, input.getHeight() / 2, input.getWidth() / 2, paint);
+ return output;
+ }
+
+ private void queryForUserInformation() {
+ Context currentUserContext;
+ UserInfo userInfo;
+ try {
+ userInfo = ActivityManagerNative.getDefault().getCurrentUser();
+ currentUserContext = mContext.createPackageContextAsUser("android", 0,
+ new UserHandle(userInfo.id));
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Couldn't create user context", e);
+ throw new RuntimeException(e);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Couldn't get user info", e);
+ throw new RuntimeException(e);
+ }
+ final int userId = userInfo.id;
+ final String userName = userInfo.name;
+
+ final Context context = currentUserContext;
+ mUserInfoTask = new AsyncTask<Void, Void, Pair<String, Drawable>>() {
+ @Override
+ protected Pair<String, Drawable> doInBackground(Void... params) {
+ final UserManager um = UserManager.get(mContext);
+
+ // Fall back to the UserManager nickname if we can't read the name from the local
+ // profile below.
+ String name = userName;
+ Drawable avatar = null;
+ Bitmap rawAvatar = um.getUserIcon(userId);
+ if (rawAvatar != null) {
+ avatar = new BitmapDrawable(mContext.getResources(), circularClip(rawAvatar));
+ } else {
+ avatar = mContext.getResources().getDrawable(R.drawable.ic_qs_default_user);
+ mUseDefaultAvatar = true;
+ }
+
+ // If it's a single-user device, get the profile name, since the nickname is not
+ // usually valid
+ if (um.getUsers().size() <= 1) {
+ // Try and read the display name from the local profile
+ final Cursor cursor = context.getContentResolver().query(
+ ContactsContract.Profile.CONTENT_URI, new String[] {
+ ContactsContract.CommonDataKinds.Phone._ID, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME},
+ null, null, null);
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ name = cursor.getString(cursor.getColumnIndex(
+ ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+ return new Pair<String, Drawable>(name, avatar);
+ }
+
+ @Override
+ protected void onPostExecute(Pair<String, Drawable> result) {
+ mUserName = result.first;
+ mUserDrawable = result.second;
+ mUserInfoTask = null;
+ notifyChanged();
+ }
+ };
+ mUserInfoTask.execute();
+ }
+
+ private void notifyChanged() {
+ for (OnUserInfoChangedListener listener : mCallbacks) {
+ listener.onUserInfoChanged(mUserName, mUserDrawable);
+ }
+ }
+
+ public interface OnUserInfoChangedListener {
+ public void onUserInfoChanged(String name, Drawable picture);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index afd5068..5849afb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -80,9 +80,12 @@ public class NotificationStackScrollLayout extends ViewGroup
private Paint mDebugPaint;
private int mContentHeight;
private int mCollapsedSize;
+ private int mBottomStackSlowDownHeight;
private int mBottomStackPeekSize;
private int mEmptyMarginBottom;
private int mPaddingBetweenElements;
+ private int mPaddingBetweenElementsDimmed;
+ private int mPaddingBetweenElementsNormal;
private int mTopPadding;
/**
@@ -153,7 +156,10 @@ public class NotificationStackScrollLayout extends ViewGroup
if (DEBUG) {
int y = mCollapsedSize;
canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
- y = (int) (getLayoutHeight() - mBottomStackPeekSize - mCollapsedSize);
+ y = (int) (getLayoutHeight() - mBottomStackPeekSize
+ - mBottomStackSlowDownHeight);
+ canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
+ y = (int) (getLayoutHeight() - mBottomStackPeekSize);
canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
y = (int) getLayoutHeight();
canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
@@ -183,9 +189,20 @@ public class NotificationStackScrollLayout extends ViewGroup
.getDimensionPixelSize(R.dimen.bottom_stack_peek_amount);
mEmptyMarginBottom = context.getResources().getDimensionPixelSize(
R.dimen.notification_stack_margin_bottom);
- mPaddingBetweenElements = context.getResources()
- .getDimensionPixelSize(R.dimen.notification_padding);
mStackScrollAlgorithm = new StackScrollAlgorithm(context);
+ mPaddingBetweenElementsDimmed = context.getResources()
+ .getDimensionPixelSize(R.dimen.notification_padding_dimmed);
+ mPaddingBetweenElementsNormal = context.getResources()
+ .getDimensionPixelSize(R.dimen.notification_padding);
+ updatePadding(false);
+ }
+
+ private void updatePadding(boolean dimmed) {
+ mPaddingBetweenElements = dimmed
+ ? mPaddingBetweenElementsDimmed
+ : mPaddingBetweenElementsNormal;
+ mBottomStackSlowDownHeight = mStackScrollAlgorithm.getBottomStackSlowDownLength();
+ updateContentHeight();
}
@Override
@@ -739,15 +756,10 @@ public class NotificationStackScrollLayout extends ViewGroup
if (firstChild != null) {
int contentHeight = getContentHeight();
int firstChildMaxExpandHeight = getMaxExpandHeight(firstChild);
-
- scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight + mBottomStackPeekSize);
+ scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight + mBottomStackPeekSize
+ + mBottomStackSlowDownHeight);
if (scrollRange > 0) {
View lastChild = getLastChildNotGone();
- if (isViewExpanded(lastChild)) {
- // last child is expanded, so we have to ensure that it can exit the
- // bottom stack
- scrollRange += mCollapsedSize + mPaddingBetweenElements;
- }
// We want to at least be able collapse the first item and not ending in a weird
// end state.
scrollRange = Math.max(scrollRange, firstChildMaxExpandHeight - mCollapsedSize);
@@ -1181,7 +1193,7 @@ public class NotificationStackScrollLayout extends ViewGroup
public int getEmptyBottomMargin() {
int emptyMargin = mMaxLayoutHeight - mContentHeight;
if (needsHeightAdaption()) {
- emptyMargin = emptyMargin - mCollapsedSize - mBottomStackPeekSize;
+ emptyMargin = emptyMargin - mBottomStackSlowDownHeight - mBottomStackPeekSize;
}
return Math.max(emptyMargin, 0);
}
@@ -1226,7 +1238,9 @@ public class NotificationStackScrollLayout extends ViewGroup
* See {@link AmbientState#setDimmed}.
*/
public void setDimmed(boolean dimmed, boolean animate) {
+ mStackScrollAlgorithm.setDimmed(dimmed);
mAmbientState.setDimmed(dimmed);
+ updatePadding(dimmed);
if (animate) {
mDimmedNeedsAnimation = true;
mNeedsAnimation = true;
@@ -1311,6 +1325,7 @@ public class NotificationStackScrollLayout extends ViewGroup
// ANIMATION_TYPE_DIMMED
new AnimationFilter()
+ .animateY()
.animateScale()
.animateDimmed()
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/PiecewiseLinearIndentationFunctor.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/PiecewiseLinearIndentationFunctor.java
index 38b544f..1c37c35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/PiecewiseLinearIndentationFunctor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/PiecewiseLinearIndentationFunctor.java
@@ -38,27 +38,26 @@ public class PiecewiseLinearIndentationFunctor extends StackIndentationFunctor {
* the actual visual distance below the top card but is a maximum,
* achieved when the next card just starts transitioning into the stack and
* the stack is full.
- * If totalTransitionDistance is equal to this, we directly start at the peek,
- * otherwise the first element transitions between 0 and
- * totalTransitionDistance - peekSize.
+ * If distanceToPeekStart is 0, we directly start at the peek, otherwise the
+ * first element transitions between 0 and distanceToPeekStart.
* Visualization:
* --------------------------------------------------- ---
* | | |
- * | FIRST ITEM | | <- totalTransitionDistance
+ * | FIRST ITEM | | <- distanceToPeekStart
* | | |
- * |---------------------------------------------------| | ---
- * |__________________SECOND ITEM______________________| | | <- peekSize
- * |===================================================| _|_ _|_
+ * |---------------------------------------------------| --- ---
+ * |__________________SECOND ITEM______________________| | <- peekSize
+ * |===================================================| _|_
*
- * @param totalTransitionDistance The total transition distance an element has to go through
+ * @param distanceToPeekStart The distance to the start of the peak.
* @param linearPart The interpolation factor between the linear and the quadratic amount taken.
* This factor must be somewhere in [0 , 1]
*/
PiecewiseLinearIndentationFunctor(int maxItemsInStack,
int peekSize,
- int totalTransitionDistance,
+ int distanceToPeekStart,
float linearPart) {
- super(maxItemsInStack, peekSize, totalTransitionDistance);
+ super(maxItemsInStack, peekSize, distanceToPeekStart);
mBaseValues = new ArrayList<Float>(maxItemsInStack+1);
initBaseValues();
mLinearPart = linearPart;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackIndentationFunctor.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackIndentationFunctor.java
index f72947a..034eba6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackIndentationFunctor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackIndentationFunctor.java
@@ -21,8 +21,8 @@ package com.android.systemui.statusbar.stack;
*/
public abstract class StackIndentationFunctor {
- protected final int mTotalTransitionDistance;
- protected final int mDistanceToPeekStart;
+ protected int mTotalTransitionDistance;
+ protected int mDistanceToPeekStart;
protected int mMaxItemsInStack;
protected int mPeekSize;
protected boolean mStackStartsAtPeek;
@@ -37,31 +37,41 @@ public abstract class StackIndentationFunctor {
* the actual visual distance below the top card but is a maximum,
* achieved when the next card just starts transitioning into the stack and
* the stack is full.
- * If totalTransitionDistance is equal to this, we directly start at the peek,
- * otherwise the first element transitions between 0 and
- * totalTransitionDistance - peekSize.
+ * If distanceToPeekStart is 0, we directly start at the peek, otherwise the
+ * first element transitions between 0 and distanceToPeekStart.
* Visualization:
* --------------------------------------------------- ---
* | | |
- * | FIRST ITEM | | <- totalTransitionDistance
+ * | FIRST ITEM | | <- distanceToPeekStart
* | | |
- * |---------------------------------------------------| | ---
- * |__________________SECOND ITEM______________________| | | <- peekSize
- * |===================================================| _|_ _|_
+ * |---------------------------------------------------| --- ---
+ * |__________________SECOND ITEM______________________| | <- peekSize
+ * |===================================================| _|_
*
- * @param totalTransitionDistance The total transition distance an element has to go through
+ * @param distanceToPeekStart The distance to the start of the peak.
*/
- StackIndentationFunctor(int maxItemsInStack, int peekSize, int totalTransitionDistance) {
- mTotalTransitionDistance = totalTransitionDistance;
- mDistanceToPeekStart = mTotalTransitionDistance - peekSize;
+ StackIndentationFunctor(int maxItemsInStack, int peekSize, int distanceToPeekStart) {
+ mDistanceToPeekStart = distanceToPeekStart;
mStackStartsAtPeek = mDistanceToPeekStart == 0;
mMaxItemsInStack = maxItemsInStack;
mPeekSize = peekSize;
+ updateTotalTransitionDistance();
}
+ private void updateTotalTransitionDistance() {
+ mTotalTransitionDistance = mDistanceToPeekStart + mPeekSize;
+ }
+
public void setPeekSize(int mPeekSize) {
this.mPeekSize = mPeekSize;
+ updateTotalTransitionDistance();
+ }
+
+ public void setDistanceToPeekStart(int distanceToPeekStart) {
+ mDistanceToPeekStart = distanceToPeekStart;
+ mStackStartsAtPeek = mDistanceToPeekStart == 0;
+ updateTotalTransitionDistance();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 5e4d496..bd9de82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -65,13 +65,40 @@ public class StackScrollAlgorithm {
private ExpandableView mFirstChildWhileExpanding;
private boolean mExpandedOnStart;
private int mTopStackTotalSize;
+ private int mPaddingBetweenElementsDimmed;
+ private int mPaddingBetweenElementsNormal;
+ private int mBottomStackSlowDownLength;
public StackScrollAlgorithm(Context context) {
initConstants(context);
+ updatePadding(false);
+ }
+
+ private void updatePadding(boolean dimmed) {
+ mPaddingBetweenElements = dimmed
+ ? mPaddingBetweenElementsDimmed
+ : mPaddingBetweenElementsNormal;
+ mTopStackTotalSize = mCollapsedSize + mPaddingBetweenElements;
+ mTopStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
+ MAX_ITEMS_IN_TOP_STACK,
+ mTopStackPeekSize,
+ mTopStackTotalSize - mTopStackPeekSize,
+ 0.5f);
+ mBottomStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
+ MAX_ITEMS_IN_BOTTOM_STACK,
+ mBottomStackPeekSize,
+ getBottomStackSlowDownLength(),
+ 0.5f);
+ }
+
+ public int getBottomStackSlowDownLength() {
+ return mBottomStackSlowDownLength + mPaddingBetweenElements;
}
private void initConstants(Context context) {
- mPaddingBetweenElements = context.getResources()
+ mPaddingBetweenElementsDimmed = context.getResources()
+ .getDimensionPixelSize(R.dimen.notification_padding_dimmed);
+ mPaddingBetweenElementsNormal = context.getResources()
.getDimensionPixelSize(R.dimen.notification_padding);
mCollapsedSize = context.getResources()
.getDimensionPixelSize(R.dimen.notification_min_height);
@@ -82,17 +109,8 @@ public class StackScrollAlgorithm {
mZDistanceBetweenElements = context.getResources()
.getDimensionPixelSize(R.dimen.z_distance_between_notifications);
mZBasicHeight = (MAX_ITEMS_IN_BOTTOM_STACK + 1) * mZDistanceBetweenElements;
- mTopStackTotalSize = mCollapsedSize + mPaddingBetweenElements;
- mTopStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
- MAX_ITEMS_IN_TOP_STACK,
- mTopStackPeekSize,
- mTopStackTotalSize,
- 0.5f);
- mBottomStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
- MAX_ITEMS_IN_BOTTOM_STACK,
- mBottomStackPeekSize,
- mCollapsedSize + mBottomStackPeekSize + mPaddingBetweenElements,
- 0.5f);
+ mBottomStackSlowDownLength = context.getResources()
+ .getDimensionPixelSize(R.dimen.bottom_stack_slow_down_length);
}
@@ -206,7 +224,7 @@ public class StackScrollAlgorithm {
float bottomPeekStart = mInnerHeight - mBottomStackPeekSize;
// The position where the bottom stack starts.
- float bottomStackStart = bottomPeekStart - mCollapsedSize;
+ float bottomStackStart = bottomPeekStart - mBottomStackSlowDownLength;
// The y coordinate of the current child.
float currentYPosition = 0.0f;
@@ -352,7 +370,7 @@ public class StackScrollAlgorithm {
algorithmState.itemsInBottomStack += algorithmState.partialInBottom;
childViewState.yTranslation = transitioningPositionStart + offset - childHeight
- mPaddingBetweenElements;
-
+
// We want at least to be at the end of the top stack when collapsing
clampPositionToTopStackEnd(childViewState, childHeight);
childViewState.location = StackScrollState.ViewState.LOCATION_MAIN_AREA;
@@ -621,6 +639,10 @@ public class StackScrollAlgorithm {
}
}
+ public void setDimmed(boolean dimmed) {
+ updatePadding(dimmed);
+ }
+
class StackScrollAlgorithmState {
/**