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/DemoMode.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIApplication.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistManager.java102
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeLog.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeService.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Recents.java146
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java107
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/DismissViewButton.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java62
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java74
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java63
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java175
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerService.java160
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java13
45 files changed, 1092 insertions, 392 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/DemoMode.java b/packages/SystemUI/src/com/android/systemui/DemoMode.java
index 9c206e2..d406f5b 100644
--- a/packages/SystemUI/src/com/android/systemui/DemoMode.java
+++ b/packages/SystemUI/src/com/android/systemui/DemoMode.java
@@ -24,6 +24,8 @@ public interface DemoMode {
public static final String ACTION_DEMO = "com.android.systemui.demo";
+ public static final String EXTRA_COMMAND = "command";
+
public static final String COMMAND_ENTER = "enter";
public static final String COMMAND_EXIT = "exit";
public static final String COMMAND_CLOCK = "clock";
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index e302c98..33bd726 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -40,13 +40,14 @@ public class SystemUIApplication extends Application {
* The classes of the stuff to start.
*/
private final Class<?>[] SERVICES = new Class[] {
+ com.android.systemui.tuner.TunerService.class,
com.android.systemui.keyguard.KeyguardViewMediator.class,
com.android.systemui.recents.Recents.class,
com.android.systemui.volume.VolumeUI.class,
com.android.systemui.statusbar.SystemBars.class,
com.android.systemui.usb.StorageNotification.class,
com.android.systemui.power.PowerUI.class,
- com.android.systemui.media.RingtonePlayer.class
+ com.android.systemui.media.RingtonePlayer.class,
};
/**
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 08659e9..3e122da 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -9,17 +9,19 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
+import android.database.ContentObserver;
import android.graphics.PixelFormat;
import android.media.AudioAttributes;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.os.Vibrator;
import android.provider.Settings;
import android.util.Log;
import android.view.Gravity;
+import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -55,6 +57,8 @@ public class AssistManager {
private final PhoneStatusBar mBar;
private final IVoiceInteractionManagerService mVoiceInteractionManagerService;
+ private ComponentName mAssistComponent;
+
private IVoiceInteractionSessionShowCallback mShowCallback =
new IVoiceInteractionSessionShowCallback.Stub() {
@@ -77,12 +81,24 @@ public class AssistManager {
}
};
+ private final ContentObserver mAssistSettingsObserver = new ContentObserver(new Handler()) {
+ @Override
+ public void onChange(boolean selfChange) {
+ updateAssistInfo();
+ }
+ };
+
public AssistManager(PhoneStatusBar bar, Context context) {
mContext = context;
mBar = bar;
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mVoiceInteractionManagerService = IVoiceInteractionManagerService.Stub.asInterface(
ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
+
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Secure.getUriFor(Settings.Secure.ASSISTANT), false,
+ mAssistSettingsObserver);
+ mAssistSettingsObserver.onChange(false);
}
public void onConfigurationChanged() {
@@ -107,22 +123,31 @@ public class AssistManager {
}
public void onGestureInvoked(boolean vibrate) {
- boolean isVoiceInteractorActive = getVoiceInteractorSupportsAssistGesture();
- if (!isVoiceInteractorActive && !isAssistantIntentAvailable()) {
+ if (mAssistComponent == null) {
return;
}
+
if (vibrate) {
vibrate();
}
- if (!isVoiceInteractorActive || !isVoiceSessionRunning()) {
+ final boolean isService = isAssistantService();
+ if (isService || !isVoiceSessionRunning()) {
showOrb();
- mView.postDelayed(mHideRunnable, isVoiceInteractorActive
+ mView.postDelayed(mHideRunnable, isService
? TIMEOUT_SERVICE
: TIMEOUT_ACTIVITY);
}
startAssist();
}
+ public void hideAssist() {
+ try {
+ mVoiceInteractionManagerService.hideCurrentSession();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to call hideCurrentSession", e);
+ }
+ }
+
private WindowManager.LayoutParams getLayoutParams() {
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
@@ -148,10 +173,12 @@ public class AssistManager {
}
private void startAssist() {
- if (getVoiceInteractorSupportsAssistGesture()) {
- startVoiceInteractor();
- } else {
- startAssistActivity();
+ if (mAssistComponent != null) {
+ if (isAssistantService()) {
+ startVoiceInteractor();
+ } else {
+ startAssistActivity();
+ }
}
}
@@ -169,6 +196,9 @@ public class AssistManager {
if (intent == null) {
return;
}
+ if (mAssistComponent != null) {
+ intent.setComponent(mAssistComponent);
+ }
try {
final ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
@@ -246,19 +276,9 @@ public class AssistManager {
}
private void maybeSwapSearchIcon() {
- Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, false, UserHandle.USER_CURRENT);
- ComponentName component = null;
- boolean isService = false;
- if (getVoiceInteractorSupportsAssistGesture()) {
- component = getVoiceInteractorComponentName();
- isService = true;
- } else if (intent != null) {
- component = intent.getComponent();
- }
- if (component != null) {
- replaceDrawable(mView.getOrb().getLogo(), component, ASSIST_ICON_METADATA_NAME,
- isService);
+ if (mAssistComponent != null) {
+ replaceDrawable(mView.getOrb().getLogo(), mAssistComponent, ASSIST_ICON_METADATA_NAME,
+ isAssistantService());
} else {
mView.getOrb().getLogo().setImageDrawable(null);
}
@@ -296,17 +316,35 @@ public class AssistManager {
}
private void vibrate() {
- if (Settings.System.getIntForUser(mContext.getContentResolver(),
- Settings.System.HAPTIC_FEEDBACK_ENABLED, 1, UserHandle.USER_CURRENT) != 0) {
- Resources res = mContext.getResources();
- Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
- vibrator.vibrate(res.getInteger(R.integer.config_search_panel_view_vibration_duration),
- VIBRATION_ATTRIBUTES);
- }
+ mView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}
- public boolean isAssistantIntentAvailable() {
- return ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
+ private boolean isAssistantService() {
+ return mAssistComponent == null ?
+ false : mAssistComponent.equals(getVoiceInteractorComponentName());
+ }
+
+ private void updateAssistInfo() {
+ final String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+ Settings.Secure.ASSISTANT, UserHandle.USER_CURRENT);
+ if (setting != null) {
+ mAssistComponent = ComponentName.unflattenFromString(setting);
+ return;
+ }
+
+ // Fallback to keep backward compatible behavior when there is no user setting.
+ if (getVoiceInteractorSupportsAssistGesture()) {
+ mAssistComponent = getVoiceInteractorComponentName();
+ return;
+ }
+
+ Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+ .getAssistIntent(mContext, false, UserHandle.USER_CURRENT);
+ if (intent != null) {
+ mAssistComponent = intent.getComponent();
+ return;
+ }
+
+ mAssistComponent = null;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
index 1f3a830..3f72125 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
@@ -82,11 +82,9 @@ public class DozeLog {
sNotificationPulseStats.append();
}
- public static void traceDozing(Context context, boolean dozing) {
- if (!ENABLED) return;
- sPulsing = false;
+ private static void init(Context context) {
synchronized (DozeLog.class) {
- if (dozing && sMessages == null) {
+ if (sMessages == null) {
sTimes = new long[SIZE];
sMessages = new String[SIZE];
sSince = System.currentTimeMillis();
@@ -105,6 +103,12 @@ public class DozeLog {
KeyguardUpdateMonitor.getInstance(context).registerCallback(sKeyguardCallback);
}
}
+ }
+
+ public static void traceDozing(Context context, boolean dozing) {
+ if (!ENABLED) return;
+ sPulsing = false;
+ init(context);
log("dozing " + dozing);
}
@@ -146,10 +150,12 @@ public class DozeLog {
}
}
- public static void traceProximityResult(boolean near, long millis, int pulseReason) {
+ public static void traceProximityResult(Context context, boolean near, long millis,
+ int pulseReason) {
if (!ENABLED) return;
log("proximityResult reason=" + pulseReasonToString(pulseReason) + " near=" + near
+ " millis=" + millis);
+ init(context);
sProxStats[pulseReason][near ? 0 : 1].append();
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 8d27450..5d46712 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -235,7 +235,7 @@ public class DozeService extends DreamService {
public void onProximityResult(int result) {
final boolean isNear = result == RESULT_NEAR;
final long end = SystemClock.uptimeMillis();
- DozeLog.traceProximityResult(isNear, end - start, reason);
+ DozeLog.traceProximityResult(mContext, isNear, end - start, reason);
if (nonBlocking) {
// we already continued
return;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 0dcc0b9..f00fed5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -455,7 +455,7 @@ public class KeyguardViewMediator extends SystemUI {
@Override
public void onFingerprintAuthenticated(int userId) {
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
- mViewMediatorCallback.keyguardDone(true);
+ mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated();
} else {
mStatusBarKeyguardViewManager.animateCollapsePanels(
FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
@@ -658,7 +658,7 @@ public class KeyguardViewMediator extends SystemUI {
mPendingLock = true;
}
- if (mPendingLock || mPendingReset) {
+ if (mPendingLock) {
playSounds(true);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index 88d0997..2a84362 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -96,6 +96,7 @@ public class MediaProjectionPermissionActivity extends Activity
.create();
mDialog.create();
+ mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setFilterTouchesWhenObscured(true);
((CheckBox) mDialog.findViewById(R.id.remember)).setOnCheckedChangeListener(this);
mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index cd4f299..25e3d10 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -111,6 +111,8 @@ public class QSPanel extends ViewGroup {
mDetailDoneButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
+ announceForAccessibility(
+ mContext.getString(R.string.accessibility_desc_quick_settings));
closeDetail();
}
});
@@ -392,6 +394,9 @@ public class QSPanel extends ViewGroup {
mDetail.bringToFront();
mDetailContent.addView(r.detailView);
MetricsLogger.visible(mContext, detailAdapter.getMetricsCategory());
+ announceForAccessibility(mContext.getString(
+ R.string.accessibility_quick_settings_detail,
+ mContext.getString(detailAdapter.getTitle())));
setDetailRecord(r);
listener = mHideGridContentWhenDone;
if (r instanceof TileRecord) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index c06ea66..937615a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -92,7 +92,7 @@ public class CastTile extends QSTile<QSTile.BooleanState> {
@Override
protected void handleUpdateState(BooleanState state, Object arg) {
- state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing());
+ state.visible = !(mKeyguard.isSecure() && mKeyguard.isShowing() && !mKeyguard.isTrusted());
state.label = mContext.getString(R.string.quick_settings_cast_title);
state.value = false;
state.autoMirrorDrawable = false;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index 0369ab5..5d74604 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -74,7 +74,11 @@ public class FlashlightTile extends QSTile<QSTile.BooleanState> implements
state.visible = mFlashlightController.isAvailable();
state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
if (arg instanceof UserBoolean) {
- state.value = ((UserBoolean) arg).value;
+ boolean value = ((UserBoolean) arg).value;
+ if (value == state.value) {
+ return;
+ }
+ state.value = value;
}
final AnimationIcon icon = state.value ? mEnable : mDisable;
icon.setAllowAnimation(arg instanceof UserBoolean && ((UserBoolean) arg).userInitiated);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index bbd3e60..442af90 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -32,6 +32,7 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
+import android.os.AsyncTask;
import android.os.Handler;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -40,6 +41,7 @@ import android.util.Pair;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
+
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.SystemUI;
@@ -184,12 +186,16 @@ public class Recents extends SystemUI
// Header (for transition)
TaskViewHeader mHeaderBar;
+ final Object mHeaderBarLock = new Object();
TaskStackView mDummyStackView;
// Variables to keep track of if we need to start recents after binding
boolean mTriggeredFromAltTab;
long mLastToggleTime;
+ Bitmap mThumbnailTransitionBitmapCache;
+ Task mThumbnailTransitionBitmapCacheKey;
+
public Recents() {
}
@@ -359,14 +365,19 @@ public class Recents extends SystemUI
void preloadRecentsInternal() {
// Preload only the raw task list into a new load plan (which will be consumed by the
- // RecentsActivity)
+ // RecentsActivity) only if there is a task to animate to.
+ ActivityManager.RunningTaskInfo topTask = mSystemServicesProxy.getTopMostTask();
+ MutableBoolean topTaskHome = new MutableBoolean(true);
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
sInstanceLoadPlan = loader.createLoadPlan(mContext);
-
- ActivityManager.RunningTaskInfo topTask = mSystemServicesProxy.getTopMostTask();
- MutableBoolean isTopTaskHome = new MutableBoolean(true);
- if (topTask != null && mSystemServicesProxy.isRecentsTopMost(topTask, isTopTaskHome)) {
- sInstanceLoadPlan.preloadRawTasks(isTopTaskHome.value);
+ if (topTask != null && !mSystemServicesProxy.isRecentsTopMost(topTask, topTaskHome)) {
+ sInstanceLoadPlan.preloadRawTasks(topTaskHome.value);
+ loader.preloadTasks(sInstanceLoadPlan, topTaskHome.value);
+ TaskStack top = sInstanceLoadPlan.getAllTaskStacks().get(0);
+ if (top.getTaskCount() > 0) {
+ preCacheThumbnailTransitionBitmapAsync(topTask, top, mDummyStackView,
+ topTaskHome.value);
+ }
}
}
@@ -513,12 +524,14 @@ public class Recents extends SystemUI
algo.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds);
Rect taskViewSize = algo.getUntransformedTaskViewSize();
int taskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
- mHeaderBar = (TaskViewHeader) mInflater.inflate(R.layout.recents_task_view_header, null,
- false);
- mHeaderBar.measure(
- View.MeasureSpec.makeMeasureSpec(taskViewSize.width(), View.MeasureSpec.EXACTLY),
- View.MeasureSpec.makeMeasureSpec(taskBarHeight, View.MeasureSpec.EXACTLY));
- mHeaderBar.layout(0, 0, taskViewSize.width(), taskBarHeight);
+ synchronized (mHeaderBarLock) {
+ mHeaderBar = (TaskViewHeader) mInflater.inflate(R.layout.recents_task_view_header, null,
+ false);
+ mHeaderBar.measure(
+ View.MeasureSpec.makeMeasureSpec(taskViewSize.width(), View.MeasureSpec.EXACTLY),
+ View.MeasureSpec.makeMeasureSpec(taskBarHeight, View.MeasureSpec.EXACTLY));
+ mHeaderBar.layout(0, 0, taskViewSize.width(), taskBarHeight);
+ }
}
/** Prepares the search bar app widget */
@@ -607,30 +620,27 @@ public class Recents extends SystemUI
*/
ActivityOptions getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo topTask,
TaskStack stack, TaskStackView stackView) {
+
// Update the destination rect
Task toTask = new Task();
TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView,
topTask.id, toTask);
- if (toTransform != null && toTask.key != null) {
- Rect toTaskRect = toTransform.rect;
- int toHeaderWidth = (int) (mHeaderBar.getMeasuredWidth() * toTransform.scale);
- int toHeaderHeight = (int) (mHeaderBar.getMeasuredHeight() * toTransform.scale);
- Bitmap thumbnail = Bitmap.createBitmap(toHeaderWidth, toHeaderHeight,
- Bitmap.Config.ARGB_8888);
- if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
- thumbnail.eraseColor(0xFFff0000);
- } else {
- Canvas c = new Canvas(thumbnail);
- c.scale(toTransform.scale, toTransform.scale);
- mHeaderBar.rebindToTask(toTask);
- mHeaderBar.draw(c);
- c.setBitmap(null);
- }
- Bitmap thumbnailImmutable = thumbnail.createAshmemBitmap();
-
+ Rect toTaskRect = toTransform.rect;
+ Bitmap thumbnail;
+ if (mThumbnailTransitionBitmapCacheKey != null
+ && mThumbnailTransitionBitmapCacheKey.key != null
+ && mThumbnailTransitionBitmapCacheKey.key.equals(toTask.key)) {
+ thumbnail = mThumbnailTransitionBitmapCache;
+ mThumbnailTransitionBitmapCacheKey = null;
+ mThumbnailTransitionBitmapCache = null;
+ } else {
+ preloadIcon(topTask);
+ thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform);
+ }
+ if (thumbnail != null) {
mStartAnimationTriggered = false;
return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
- thumbnailImmutable, toTaskRect.left, toTaskRect.top, toTaskRect.width(),
+ thumbnail, toTaskRect.left, toTaskRect.top, toTaskRect.width(),
toTaskRect.height(), mHandler, this);
}
@@ -638,6 +648,72 @@ public class Recents extends SystemUI
return getUnknownTransitionActivityOptions();
}
+ /**
+ * Preloads the icon of a task.
+ */
+ void preloadIcon(ActivityManager.RunningTaskInfo task) {
+
+ // Ensure that we load the running task's icon
+ RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
+ launchOpts.runningTaskId = task.id;
+ launchOpts.loadThumbnails = false;
+ launchOpts.onlyLoadForCache = true;
+ RecentsTaskLoader.getInstance().loadTasks(mContext, sInstanceLoadPlan, launchOpts);
+ }
+
+ /**
+ * Caches the header thumbnail used for a window animation asynchronously into
+ * {@link #mThumbnailTransitionBitmapCache}.
+ */
+ void preCacheThumbnailTransitionBitmapAsync(ActivityManager.RunningTaskInfo topTask,
+ TaskStack stack, TaskStackView stackView, boolean isTopTaskHome) {
+ preloadIcon(topTask);
+
+ // Update the destination rect
+ mDummyStackView.updateMinMaxScrollForStack(stack, mTriggeredFromAltTab, isTopTaskHome);
+ final Task toTask = new Task();
+ final TaskViewTransform toTransform = getThumbnailTransitionTransform(stack, stackView,
+ topTask.id, toTask);
+ new AsyncTask<Void, Void, Bitmap>() {
+ @Override
+ protected Bitmap doInBackground(Void... params) {
+ return drawThumbnailTransitionBitmap(toTask, toTransform);
+ }
+
+ @Override
+ protected void onPostExecute(Bitmap bitmap) {
+ mThumbnailTransitionBitmapCache = bitmap;
+ mThumbnailTransitionBitmapCacheKey = toTask;
+ }
+ }.execute();
+ }
+
+ /**
+ * Draws the header of a task used for the window animation into a bitmap.
+ */
+ Bitmap drawThumbnailTransitionBitmap(Task toTask, TaskViewTransform toTransform) {
+ if (toTransform != null && toTask.key != null) {
+ Bitmap thumbnail;
+ synchronized (mHeaderBarLock) {
+ int toHeaderWidth = (int) (mHeaderBar.getMeasuredWidth() * toTransform.scale);
+ int toHeaderHeight = (int) (mHeaderBar.getMeasuredHeight() * toTransform.scale);
+ thumbnail = Bitmap.createBitmap(toHeaderWidth, toHeaderHeight,
+ Bitmap.Config.ARGB_8888);
+ if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
+ thumbnail.eraseColor(0xFFff0000);
+ } else {
+ Canvas c = new Canvas(thumbnail);
+ c.scale(toTransform.scale, toTransform.scale);
+ mHeaderBar.rebindToTask(toTask);
+ mHeaderBar.draw(c);
+ c.setBitmap(null);
+ }
+ }
+ return thumbnail.createAshmemBitmap();
+ }
+ return null;
+ }
+
/** Returns the transition rect for the given task id. */
TaskViewTransform getThumbnailTransitionTransform(TaskStack stack, TaskStackView stackView,
int runningTaskId, Task runningTaskOut) {
@@ -694,7 +770,9 @@ public class Recents extends SystemUI
return;
}
- loader.preloadTasks(sInstanceLoadPlan, isTopTaskHome);
+ if (!sInstanceLoadPlan.hasTasks()) {
+ loader.preloadTasks(sInstanceLoadPlan, isTopTaskHome);
+ }
ArrayList<TaskStack> stacks = sInstanceLoadPlan.getAllTaskStacks();
TaskStack stack = stacks.get(0);
@@ -706,12 +784,6 @@ public class Recents extends SystemUI
boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks;
if (useThumbnailTransition) {
- // Ensure that we load the running task's icon
- RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
- launchOpts.runningTaskId = topTask.id;
- launchOpts.loadThumbnails = false;
- launchOpts.onlyLoadForCache = true;
- loader.loadTasks(mContext, sInstanceLoadPlan, launchOpts);
// Try starting with a thumbnail transition
ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, stack,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index ad97f91..3885799 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -81,6 +81,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Runnables to finish the Recents activity
FinishRecentsRunnable mFinishLaunchHomeRunnable;
+ // Runnable to be executed after we paused ourselves
+ Runnable mAfterPauseRunnable;
+
/**
* A common Runnable to finish Recents either by calling finish() (with a custom animation) or
* launching Home with some ActivityOptions. Generally we always launch home when we exit
@@ -441,6 +444,19 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
if (mConfig.launchedHasConfigurationChanged) {
onEnterAnimationTriggered();
}
+
+ if (!mConfig.launchedHasConfigurationChanged) {
+ mRecentsView.disableLayersForOneFrame();
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (mAfterPauseRunnable != null) {
+ mRecentsView.post(mAfterPauseRunnable);
+ mAfterPauseRunnable = null;
+ }
}
@Override
@@ -624,6 +640,11 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
Recents.startScreenPinning(this, ssp);
}
+ @Override
+ public void runAfterPause(Runnable r) {
+ mAfterPauseRunnable = r;
+ }
+
/**** RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks Implementation ****/
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java b/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java
index 4b5c0bd..3f5d0a8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java
@@ -73,4 +73,9 @@ public class FixedSizeImageView extends ImageView {
mAllowRelayout = true;
mAllowInvalidate = true;
}
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
}
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 cec613c..fa97a86 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -24,14 +24,19 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.net.Uri;
+import android.os.Bundle;
+import android.os.IRemoteCallback;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewStub;
import android.view.WindowInsets;
+import android.view.WindowManagerGlobal;
import android.widget.FrameLayout;
+
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsAppWidgetHostView;
@@ -52,6 +57,8 @@ import java.util.List;
public class RecentsView extends FrameLayout implements TaskStackView.TaskStackViewCallbacks,
RecentsPackageMonitor.PackageCallbacks {
+ private static final String TAG = "RecentsView";
+
/** The RecentsView callbacks */
public interface RecentsViewCallbacks {
public void onTaskViewClicked();
@@ -59,8 +66,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
public void onAllTaskViewsDismissed();
public void onExitToHomeAnimationTriggered();
public void onScreenPinningRequest();
-
public void onTaskResize(Task t);
+ public void runAfterPause(Runnable r);
}
RecentsConfiguration mConfig;
@@ -431,11 +438,75 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
return false;
}
+ public void disableLayersForOneFrame() {
+ List<TaskStackView> stackViews = getTaskStackViews();
+ for (int i = 0; i < stackViews.size(); i++) {
+ stackViews.get(i).disableLayersForOneFrame();
+ }
+ }
+
+ private void postDrawHeaderThumbnailTransitionRunnable(final TaskView tv, final int offsetX,
+ final int offsetY, final TaskViewTransform transform,
+ final ActivityOptions.OnAnimationStartedListener animStartedListener) {
+ Runnable r = new Runnable() {
+ @Override
+ public void run() {
+ // Disable any focused state before we draw the header
+ if (tv.isFocusedTask()) {
+ tv.unsetFocusedTask();
+ }
+
+ float scale = tv.getScaleX();
+ int fromHeaderWidth = (int) (tv.mHeaderView.getMeasuredWidth() * scale);
+ int fromHeaderHeight = (int) (tv.mHeaderView.getMeasuredHeight() * scale);
+
+ Bitmap b = Bitmap.createBitmap(fromHeaderWidth, fromHeaderHeight,
+ Bitmap.Config.ARGB_8888);
+ if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
+ b.eraseColor(0xFFff0000);
+ } else {
+ Canvas c = new Canvas(b);
+ c.scale(tv.getScaleX(), tv.getScaleY());
+ tv.mHeaderView.draw(c);
+ c.setBitmap(null);
+ }
+ b = b.createAshmemBitmap();
+ int[] pts = new int[2];
+ tv.getLocationOnScreen(pts);
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .overridePendingAppTransitionAspectScaledThumb(b,
+ pts[0] + offsetX,
+ pts[1] + offsetY,
+ transform.rect.width(),
+ transform.rect.height(),
+ new IRemoteCallback.Stub() {
+ @Override
+ public void sendResult(Bundle data)
+ throws RemoteException {
+ post(new Runnable() {
+ @Override
+ public void run() {
+ if (animStartedListener != null) {
+ animStartedListener.onAnimationStarted();
+ }
+ }
+ });
+ }
+ }, true);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error overriding app transition", e);
+ }
+ }
+ };
+ mCb.runAfterPause(r);
+ }
/**** TaskStackView.TaskStackCallbacks Implementation ****/
@Override
public void onTaskViewClicked(final TaskStackView stackView, final TaskView tv,
final TaskStack stack, final Task task, final boolean lockToTask) {
+
// Notify any callbacks of the launching of a new task
if (mCb != null) {
mCb.onTaskViewClicked();
@@ -466,31 +537,6 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
ActivityOptions opts = null;
if (task.thumbnail != null && task.thumbnail.getWidth() > 0 &&
task.thumbnail.getHeight() > 0) {
- Bitmap b;
- if (tv != null) {
- // Disable any focused state before we draw the header
- if (tv.isFocusedTask()) {
- tv.unsetFocusedTask();
- }
-
- float scale = tv.getScaleX();
- int fromHeaderWidth = (int) (tv.mHeaderView.getMeasuredWidth() * scale);
- int fromHeaderHeight = (int) (tv.mHeaderView.getMeasuredHeight() * scale);
- b = Bitmap.createBitmap(fromHeaderWidth, fromHeaderHeight,
- Bitmap.Config.ARGB_8888);
- if (Constants.DebugFlags.App.EnableTransitionThumbnailDebugMode) {
- b.eraseColor(0xFFff0000);
- } else {
- Canvas c = new Canvas(b);
- c.scale(tv.getScaleX(), tv.getScaleY());
- tv.mHeaderView.draw(c);
- c.setBitmap(null);
- }
- } else {
- // Notify the system to skip the thumbnail layer by using an ALPHA_8 bitmap
- b = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
- }
- Bitmap bImmut = b.createAshmemBitmap();
ActivityOptions.OnAnimationStartedListener animStartedListener = null;
if (lockToTask) {
animStartedListener = new ActivityOptions.OnAnimationStartedListener() {
@@ -509,6 +555,10 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
};
}
+ if (tv != null) {
+ postDrawHeaderThumbnailTransitionRunnable(tv, offsetX, offsetY, transform,
+ animStartedListener);
+ }
if (mConfig.multiStackEnabled) {
opts = ActivityOptions.makeCustomAnimation(sourceView.getContext(),
R.anim.recents_from_unknown_enter,
@@ -516,7 +566,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
sourceView.getHandler(), animStartedListener);
} else {
opts = ActivityOptions.makeThumbnailAspectScaleUpAnimation(sourceView,
- bImmut, offsetX, offsetY, transform.rect.width(), transform.rect.height(),
+ Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8).createAshmemBitmap(),
+ offsetX, offsetY, transform.rect.width(), transform.rect.height(),
sourceView.getHandler(), animStartedListener);
}
}
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 5f151e8..5711cd6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -19,6 +19,7 @@ package com.android.systemui.recents.views;
import android.animation.ValueAnimator;
import android.content.ComponentName;
import android.content.Context;
+import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.view.LayoutInflater;
@@ -63,7 +64,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
public void onTaskResize(Task t);
}
-
RecentsConfiguration mConfig;
TaskStack mStack;
@@ -81,7 +81,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
boolean mDismissAllButtonAnimating;
int mFocusedTaskIndex = -1;
int mPrevAccessibilityFocusedIndex = -1;
-
// Optimizations
int mStackViewsAnimationDuration;
boolean mStackViewsDirty = true;
@@ -99,6 +98,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
ArrayList<TaskView> mTaskViews = new ArrayList<TaskView>();
List<TaskView> mImmutableTaskViews = new ArrayList<TaskView>();
LayoutInflater mInflater;
+ boolean mLayersDisabled;
// A convenience update listener to request updating clipping of tasks
ValueAnimator.AnimatorUpdateListener mRequestUpdateClippingListener =
@@ -375,7 +375,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
if (tv == null) {
tv = mViewPool.pickUpViewFromPool(task, task);
-
+ if (mLayersDisabled) {
+ tv.disableLayersForOneFrame();
+ }
if (mStackViewsAnimationDuration > 0) {
// For items in the list, put them in start animating them from the
// approriate ends of the list where they are expected to appear
@@ -1031,6 +1033,20 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mUIDozeTrigger.poke();
}
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ mLayersDisabled = false;
+ super.dispatchDraw(canvas);
+ }
+
+ public void disableLayersForOneFrame() {
+ mLayersDisabled = true;
+ List<TaskView> taskViews = getTaskViews();
+ for (int i = 0; i < taskViews.size(); i++) {
+ taskViews.get(i).disableLayersForOneFrame();
+ }
+ }
+
/**** TaskStackCallbacks Implementation ****/
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 01ed08a..5906ef1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -22,6 +22,7 @@ import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.*;
import android.util.AttributeSet;
+import android.view.accessibility.AccessibilityManager;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.view.animation.AccelerateInterpolator;
@@ -366,7 +367,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
.setStartDelay(delay)
.setDuration(duration)
.setInterpolator(PhoneStatusBar.ALPHA_IN)
- .withLayer()
.start();
}
@@ -415,7 +415,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
.setStartDelay(0)
.setDuration(mConfig.taskViewExitToAppDuration)
.setInterpolator(mConfig.fastOutLinearInInterpolator)
- .withLayer()
.start();
} else {
// Hide the dismiss button
@@ -650,6 +649,10 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
}
}
+ public void disableLayersForOneFrame() {
+ mHeaderView.disableLayersForOneFrame();
+ }
+
/**** TaskCallbacks Implementation ****/
/** Binds this task view to the task */
@@ -672,7 +675,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mThumbnailView.rebindToTask(mTask);
mHeaderView.rebindToTask(mTask);
// Rebind any listeners
- mHeaderView.mApplicationIcon.setOnClickListener(this);
+ AccessibilityManager am = (AccessibilityManager) getContext().
+ getSystemService(Context.ACCESSIBILITY_SERVICE);
+ if (Constants.DebugFlags.App.EnableTaskFiltering || (am != null && am.isEnabled())) {
+ mHeaderView.mApplicationIcon.setOnClickListener(this);
+ }
mHeaderView.mDismissButton.setOnClickListener(this);
if (mConfig.multiStackEnabled) {
mHeaderView.mMoveTaskButton.setOnClickListener(this);
@@ -718,9 +725,19 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
postDelayed(new Runnable() {
@Override
public void run() {
- if (Constants.DebugFlags.App.EnableTaskFiltering && v == mHeaderView.mApplicationIcon) {
- if (mCb != null) {
- mCb.onTaskViewAppIconClicked(tv);
+ if (v == mHeaderView.mApplicationIcon) {
+ if (Constants.DebugFlags.App.EnableTaskFiltering) {
+ if (mCb != null) {
+ mCb.onTaskViewAppIconClicked(tv);
+ }
+ } else {
+ AccessibilityManager am = (AccessibilityManager) getContext().
+ getSystemService(Context.ACCESSIBILITY_SERVICE);
+ if (am != null && am.isEnabled()) {
+ if (mCb != null) {
+ mCb.onTaskViewAppInfoClicked(tv);
+ }
+ }
}
} else if (v == mHeaderView.mDismissButton) {
dismissTask();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index f397bc3..6db4020 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -26,6 +26,7 @@ import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.RippleDrawable;
@@ -80,6 +81,8 @@ public class TaskViewHeader extends FrameLayout {
Paint mDimLayerPaint = new Paint();
PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP);
+ boolean mLayersDisabled;
+
public TaskViewHeader(Context context) {
this(context, null);
}
@@ -172,7 +175,9 @@ public class TaskViewHeader extends FrameLayout {
void setDimAlpha(int alpha) {
mDimColorFilter.setColor(Color.argb(alpha, 0, 0, 0));
mDimLayerPaint.setColorFilter(mDimColorFilter);
- setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint);
+ if (!mLayersDisabled) {
+ setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint);
+ }
}
/** Returns the secondary color for a primary color. */
@@ -190,14 +195,14 @@ public class TaskViewHeader extends FrameLayout {
} else if (t.applicationIcon != null) {
mApplicationIcon.setImageDrawable(t.applicationIcon);
}
- mApplicationIcon.setContentDescription(t.contentDescription);
if (!mActivityDescription.getText().toString().equals(t.activityLabel)) {
mActivityDescription.setText(t.activityLabel);
}
mActivityDescription.setContentDescription(t.contentDescription);
// Try and apply the system ui tint
- int existingBgColor = getBackgroundColor();
+ int existingBgColor = (getBackground() instanceof ColorDrawable) ?
+ ((ColorDrawable) getBackground()).getColor() : 0;
if (existingBgColor != t.colorPrimary) {
mBackgroundColorDrawable.setColor(t.colorPrimary);
mBackgroundColor = t.colorPrimary;
@@ -263,7 +268,6 @@ public class TaskViewHeader extends FrameLayout {
.setStartDelay(0)
.setInterpolator(mConfig.fastOutSlowInInterpolator)
.setDuration(mConfig.taskViewExitToAppDuration)
- .withLayer()
.start();
}
}
@@ -278,7 +282,6 @@ public class TaskViewHeader extends FrameLayout {
.setStartDelay(0)
.setInterpolator(mConfig.fastOutLinearInInterpolator)
.setDuration(mConfig.taskViewEnterFromAppDuration)
- .withLayer()
.start();
}
}
@@ -305,6 +308,28 @@ public class TaskViewHeader extends FrameLayout {
return new int[] {};
}
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+ if (mLayersDisabled) {
+ mLayersDisabled = false;
+ postOnAnimation(new Runnable() {
+ @Override
+ public void run() {
+ mLayersDisabled = false;
+ setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint);
+ }
+ });
+ }
+ }
+
+ public void disableLayersForOneFrame() {
+ mLayersDisabled = true;
+
+ // Disable layer for a frame so we can draw our first frame faster.
+ setLayerType(LAYER_TYPE_NONE, null);
+ }
+
/** Notifies the associated TaskView has been focused. */
void onTaskViewFocusChanged(boolean focused, boolean animateFocusedState) {
// If we are not animating the visible state, just return
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index fa172a4..c945fc9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -92,6 +92,7 @@ import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.SwipeHelper;
import com.android.systemui.SystemUI;
+import com.android.systemui.assist.AssistManager;
import com.android.systemui.recents.Recents;
import com.android.systemui.statusbar.NotificationData.Entry;
import com.android.systemui.statusbar.phone.NavigationBarView;
@@ -240,6 +241,8 @@ public abstract class BaseStatusBar extends SystemUI implements
private NotificationClicker mNotificationClicker = new NotificationClicker();
+ protected AssistManager mAssistManager;
+
@Override // NotificationData.Environment
public boolean isDeviceProvisioned() {
return mDeviceProvisioned;
@@ -1030,9 +1033,7 @@ public abstract class BaseStatusBar extends SystemUI implements
@Override
public void toggleRecentApps() {
- int msg = MSG_TOGGLE_RECENTS_APPS;
- mHandler.removeMessages(msg);
- mHandler.sendEmptyMessage(msg);
+ toggleRecents();
}
@Override
@@ -1628,6 +1629,7 @@ public abstract class BaseStatusBar extends SystemUI implements
// TODO: Dismiss Keyguard.
}
if (intent.isActivity()) {
+ mAssistManager.hideAssist();
overrideActivityPendingAppTransition(keyguardShowing
&& !afterKeyguardGone);
}
@@ -1646,7 +1648,7 @@ public abstract class BaseStatusBar extends SystemUI implements
true /* force */, true /* delayed */);
visibilityChanged(false);
- return intent != null && intent.isActivity();
+ return true;
}
}, afterKeyguardGone);
}
@@ -1904,7 +1906,7 @@ public abstract class BaseStatusBar extends SystemUI implements
logUpdate(entry, n);
}
boolean applyInPlace = shouldApplyInPlace(entry, n);
- boolean shouldInterrupt = shouldInterrupt(notification);
+ boolean shouldInterrupt = shouldInterrupt(entry);
boolean alertAgain = alertAgain(entry, n);
entry.notification = notification;
@@ -2075,7 +2077,8 @@ public abstract class BaseStatusBar extends SystemUI implements
|| (newNotification.flags & Notification.FLAG_ONLY_ALERT_ONCE) == 0;
}
- protected boolean shouldInterrupt(StatusBarNotification sbn) {
+ protected boolean shouldInterrupt(Entry entry) {
+ StatusBarNotification sbn = entry.notification;
if (mNotificationData.shouldFilterOut(sbn)) {
if (DEBUG) {
Log.d(TAG, "Skipping HUN check for " + sbn.getKey() + " since it's filtered out.");
@@ -2100,10 +2103,12 @@ public abstract class BaseStatusBar extends SystemUI implements
Notification.HEADS_UP_ALLOWED) != Notification.HEADS_UP_NEVER;
boolean accessibilityForcesLaunch = isFullscreen
&& mAccessibilityManager.isTouchExplorationEnabled();
+ boolean justLaunchedFullScreenIntent = entry.hasJustLaunchedFullScreenIntent();
boolean interrupt = (isFullscreen || (isHighPriority && (isNoisy || hasTicker)))
&& isAllowed
&& !accessibilityForcesLaunch
+ && !justLaunchedFullScreenIntent
&& mPowerManager.isScreenOn()
&& (!mStatusBarKeyguardViewManager.isShowing()
|| mStatusBarKeyguardViewManager.isOccluded())
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewButton.java
index 00665f4..a323684 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DismissViewButton.java
@@ -48,15 +48,14 @@ public class DismissViewButton extends Button {
public DismissViewButton(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- mAnimatedDismissDrawable = (AnimatedVectorDrawable) getContext().getResources().getDrawable(
+ mAnimatedDismissDrawable = (AnimatedVectorDrawable) getContext().getDrawable(
R.drawable.dismiss_all_shape_animation).mutate();
mAnimatedDismissDrawable.setCallback(this);
mAnimatedDismissDrawable.setBounds(0,
0,
mAnimatedDismissDrawable.getIntrinsicWidth(),
mAnimatedDismissDrawable.getIntrinsicHeight());
- mStaticDismissDrawable = getContext().getResources().getDrawable(
- R.drawable.dismiss_all_shape);
+ mStaticDismissDrawable = getContext().getDrawable(R.drawable.dismiss_all_shape);
mStaticDismissDrawable.setBounds(0,
0,
mStaticDismissDrawable.getIntrinsicWidth(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 9ef495d..d444ea8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -903,12 +903,18 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
return mShowingPublic ? mPublicLayout : mPrivateLayout;
}
+ @Override
+ public void setShowingLegacyBackground(boolean showing) {
+ super.setShowingLegacyBackground(showing);
+ mPrivateLayout.setShowingLegacyBackground(showing);
+ mPublicLayout.setShowingLegacyBackground(showing);
+ }
+
public void setExpansionLogger(ExpansionLogger logger, String key) {
mLogger = logger;
mLoggingKey = key;
}
-
private void logExpansionEvent(boolean userAction, boolean wasExpanded) {
final boolean nowExpanded = isExpanded();
if (wasExpanded != nowExpanded && mLogger != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index 374d970..58fb2b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -60,22 +60,18 @@ public class KeyguardAffordanceView extends ImageView {
private final int mNormalColor;
private final ArgbEvaluator mColorInterpolator;
private final FlingAnimationUtils mFlingAnimationUtils;
- private final Drawable mArrowDrawable;
- private final int mHintChevronPadding;
private float mCircleRadius;
private int mCenterX;
private int mCenterY;
private ValueAnimator mCircleAnimator;
private ValueAnimator mAlphaAnimator;
private ValueAnimator mScaleAnimator;
- private ValueAnimator mArrowAnimator;
private float mCircleStartValue;
private boolean mCircleWillBeHidden;
private int[] mTempPoint = new int[2];
private float mImageScale;
private int mCircleColor;
private boolean mIsLeft;
- private float mArrowAlpha = 0.0f;
private View mPreviewView;
private float mCircleStartRadius;
private float mMaxCircleSize;
@@ -113,12 +109,6 @@ public class KeyguardAffordanceView extends ImageView {
mAlphaAnimator = null;
}
};
- private AnimatorListenerAdapter mArrowEndListener = new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mArrowAnimator = null;
- }
- };
public KeyguardAffordanceView(Context context) {
this(context, null);
@@ -144,17 +134,12 @@ public class KeyguardAffordanceView extends ImageView {
mInverseColor = 0xff000000;
mMinBackgroundRadius = mContext.getResources().getDimensionPixelSize(
R.dimen.keyguard_affordance_min_background_radius);
- mHintChevronPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.hint_chevron_circle_padding);
mAppearInterpolator = AnimationUtils.loadInterpolator(mContext,
android.R.interpolator.linear_out_slow_in);
mDisappearInterpolator = AnimationUtils.loadInterpolator(mContext,
android.R.interpolator.fast_out_linear_in);
mColorInterpolator = new ArgbEvaluator();
mFlingAnimationUtils = new FlingAnimationUtils(mContext, 0.3f);
- mArrowDrawable = context.getDrawable(R.drawable.ic_chevron_left);
- mArrowDrawable.setBounds(0, 0, mArrowDrawable.getIntrinsicWidth(),
- mArrowDrawable.getIntrinsicHeight());
}
@Override
@@ -169,7 +154,6 @@ public class KeyguardAffordanceView extends ImageView {
protected void onDraw(Canvas canvas) {
mSupportHardware = canvas.isHardwareAccelerated();
drawBackgroundCircle(canvas);
- drawArrow(canvas);
canvas.save();
canvas.scale(mImageScale, mImageScale, getWidth() / 2, getHeight() / 2);
super.onDraw(canvas);
@@ -183,22 +167,6 @@ public class KeyguardAffordanceView extends ImageView {
}
}
- private void drawArrow(Canvas canvas) {
- if (mArrowAlpha > 0) {
- canvas.save();
- canvas.translate(mCenterX, mCenterY);
- if (mIsLeft) {
- canvas.scale(-1.0f, 1.0f);
- }
- canvas.translate(- mCircleRadius - mHintChevronPadding
- - mArrowDrawable.getIntrinsicWidth() / 2,
- - mArrowDrawable.getIntrinsicHeight() / 2);
- mArrowDrawable.setAlpha((int) (mArrowAlpha * 255));
- mArrowDrawable.draw(canvas);
- canvas.restore();
- }
- }
-
private void updateIconColor() {
Drawable drawable = getDrawable().mutate();
float alpha = mCircleRadius / mMinBackgroundRadius;
@@ -533,36 +501,6 @@ public class KeyguardAffordanceView extends ImageView {
return mCircleRadius;
}
- public void showArrow(boolean show) {
- cancelAnimator(mArrowAnimator);
- float targetAlpha = show ? 1.0f : 0.0f;
- if (mArrowAlpha == targetAlpha) {
- return;
- }
- ValueAnimator animator = ValueAnimator.ofFloat(mArrowAlpha, targetAlpha);
- mArrowAnimator = animator;
- animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mArrowAlpha = (float) animation.getAnimatedValue();
- invalidate();
- }
- });
- animator.addListener(mArrowEndListener);
- Interpolator interpolator = show
- ? mAppearInterpolator
- : mDisappearInterpolator;
- animator.setInterpolator(interpolator);
- float durationFactor = Math.abs(mArrowAlpha - targetAlpha);
- long duration = (long) (NORMAL_ANIMATION_DURATION * durationFactor);
- animator.setDuration(duration);
- animator.start();
- }
-
- public void setIsLeft(boolean left) {
- mIsLeft = left;
- }
-
@Override
public boolean performClick() {
if (isClickable()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index dec2fc7..8172a4d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -67,6 +67,8 @@ public class NotificationContentView extends FrameLayout {
private final Paint mFadePaint = new Paint();
private boolean mAnimate;
private boolean mIsHeadsUp;
+ private boolean mShowingLegacyBackground;
+
private final ViewTreeObserver.OnPreDrawListener mEnableAnimationPredrawListener
= new ViewTreeObserver.OnPreDrawListener() {
@Override
@@ -421,7 +423,7 @@ public class NotificationContentView extends FrameLayout {
public void setDark(boolean dark, boolean fade, long delay) {
if (mDark == dark || mContractedChild == null) return;
mDark = dark;
- mContractedWrapper.setDark(dark, fade, delay);
+ mContractedWrapper.setDark(dark && !mShowingLegacyBackground, fade, delay);
}
public void setHeadsUp(boolean headsUp) {
@@ -436,4 +438,8 @@ public class NotificationContentView extends FrameLayout {
// layout, and saves us some layers.
return false;
}
+
+ public void setShowingLegacyBackground(boolean showing) {
+ mShowingLegacyBackground = showing;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 2a8b4ac..dbabe3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar;
import android.app.Notification;
+import android.os.SystemClock;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.NotificationListenerService.RankingMap;
@@ -41,6 +42,8 @@ public class NotificationData {
private HeadsUpManager mHeadsUpManager;
public static final class Entry {
+ private static final long LAUNCH_COOLDOWN = 2000;
+ private static final long NOT_LAUNCHED_YET = -LAUNCH_COOLDOWN;
public String key;
public StatusBarNotification notification;
public StatusBarIconView icon;
@@ -49,6 +52,7 @@ public class NotificationData {
public boolean autoRedacted; // whether the redacted notification was generated by us
public boolean legacy; // whether the notification has a legacy, dark background
public int targetSdk;
+ private long lastFullScreenIntentLaunchTime = NOT_LAUNCHED_YET;
public Entry(StatusBarNotification n, StatusBarIconView ic) {
this.key = n.getKey();
@@ -72,6 +76,7 @@ public class NotificationData {
// We should fix this at some point.
autoRedacted = false;
legacy = false;
+ lastFullScreenIntentLaunchTime = NOT_LAUNCHED_YET;
if (row != null) {
row.reset();
}
@@ -92,6 +97,14 @@ public class NotificationData {
public View getPublicContentView() {
return row.getPublicLayout().getContractedChild();
}
+
+ public void notifyFullScreenIntentLaunched() {
+ lastFullScreenIntentLaunchTime = SystemClock.elapsedRealtime();
+ }
+
+ public boolean hasJustLaunchedFullScreenIntent() {
+ return SystemClock.elapsedRealtime() < lastFullScreenIntentLaunchTime + LAUNCH_COOLDOWN;
+ }
}
private final ArrayMap<String, Entry> mEntries = new ArrayMap<>();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 02e196e..2f63c73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -18,14 +18,12 @@ package com.android.systemui.statusbar;
import android.content.Context;
import android.content.res.ColorStateList;
-import android.database.ContentObserver;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.provider.Settings;
import android.telephony.SubscriptionInfo;
+import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
@@ -40,6 +38,8 @@ import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
import com.android.systemui.statusbar.policy.SecurityController;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
import java.util.ArrayList;
import java.util.List;
@@ -48,7 +48,7 @@ import java.util.List;
public class SignalClusterView
extends LinearLayout
implements NetworkControllerImpl.SignalCallback,
- SecurityController.SecurityControllerCallback {
+ SecurityController.SecurityControllerCallback, Tunable {
static final String TAG = "SignalClusterView";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -105,14 +105,22 @@ public class SignalClusterView
public SignalClusterView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
- readBlacklist();
}
- private void readBlacklist() {
- mBlockAirplane = StatusBarIconController.isBlocked(getContext(), SLOT_AIRPLANE);
- mBlockMobile = StatusBarIconController.isBlocked(getContext(), SLOT_MOBILE);
- mBlockWifi = StatusBarIconController.isBlocked(getContext(), SLOT_WIFI);
- mBlockEthernet = StatusBarIconController.isBlocked(getContext(), SLOT_ETHERNET);
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (!StatusBarIconController.ICON_BLACKLIST.equals(key)) {
+ return;
+ }
+ ArraySet<String> blockList = StatusBarIconController.getIconBlacklist(newValue);
+ mBlockAirplane = blockList.contains(SLOT_AIRPLANE);
+ mBlockMobile = blockList.contains(SLOT_MOBILE);
+ mBlockWifi = blockList.contains(SLOT_WIFI);
+ mBlockEthernet = blockList.contains(SLOT_ETHERNET);
+
+ // Re-register to get new callbacks.
+ mNC.removeSignalCallback(SignalClusterView.this);
+ mNC.addSignalCallback(SignalClusterView.this);
}
public void setNetworkController(NetworkControllerImpl nc) {
@@ -160,12 +168,10 @@ public class SignalClusterView
for (PhoneState state : mPhoneStates) {
mMobileSignalGroup.addView(state.mMobileGroup);
}
+ TunerService.get(mContext).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
apply();
applyIconTint();
- getContext().getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(StatusBarIconController.ICON_BLACKLIST), false,
- mBlacklistObserver);
}
@Override
@@ -178,7 +184,7 @@ public class SignalClusterView
mAirplane = null;
mMobileSignalGroup.removeAllViews();
mMobileSignalGroup = null;
- getContext().getContentResolver().unregisterContentObserver(mBlacklistObserver);
+ TunerService.get(mContext).removeTunable(this);
super.onDetachedFromWindow();
}
@@ -528,14 +534,5 @@ public class SignalClusterView
setTint(mMobileType, tint);
}
}
-
- private final ContentObserver mBlacklistObserver = new ContentObserver(new Handler()) {
- public void onChange(boolean selfChange) {
- readBlacklist();
- // Re-register to get new callbacks.
- mNC.removeSignalCallback(SignalClusterView.this);
- mNC.addSignalCallback(SignalClusterView.this);
- };
- };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 64735ee..0877ff9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -127,10 +127,8 @@ public class KeyguardAffordanceHelper {
private void initIcons() {
mLeftIcon = mCallback.getLeftIcon();
- mLeftIcon.setIsLeft(true);
mCenterIcon = mCallback.getCenterIcon();
mRightIcon = mCallback.getRightIcon();
- mRightIcon.setIsLeft(false);
updatePreviews();
}
@@ -261,7 +259,6 @@ public class KeyguardAffordanceHelper {
private void startHintAnimationPhase1(final boolean right, final Runnable onFinishedListener) {
final KeyguardAffordanceView targetView = right ? mRightIcon : mLeftIcon;
- targetView.showArrow(true);
ValueAnimator animator = getAnimatorToRadius(right, mHintGrowAmount);
animator.addListener(new AnimatorListenerAdapter() {
private boolean mCancelled;
@@ -277,7 +274,6 @@ public class KeyguardAffordanceHelper {
mSwipeAnimator = null;
mTargetedView = null;
onFinishedListener.run();
- targetView.showArrow(false);
} else {
startUnlockHintAnimationPhase2(right, onFinishedListener);
}
@@ -301,14 +297,8 @@ public class KeyguardAffordanceHelper {
public void onAnimationEnd(Animator animation) {
mSwipeAnimator = null;
mTargetedView = null;
- targetView.showArrow(false);
onFinishedListener.run();
}
-
- @Override
- public void onAnimationStart(Animator animation) {
- targetView.showArrow(false);
- }
});
animator.setInterpolator(mDisappearInterpolator);
animator.setDuration(HINT_PHASE2_DURATION);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 3d57d54..3737d05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -228,4 +228,9 @@ public class KeyguardBouncer {
ensureView();
return mKeyguardView.interceptMediaKey(event);
}
+
+ public void notifyKeyguardAuthenticated() {
+ ensureView();
+ mKeyguardView.finish();
+ }
}
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 4bc317a..9e1af82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -36,6 +36,7 @@ import android.view.WindowInsets;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
import android.widget.FrameLayout;
import android.widget.TextView;
@@ -205,6 +206,10 @@ public class NotificationPanelView extends PanelView implements
}
};
+ /** Interpolator to be used for animations that respond directly to a touch */
+ private final Interpolator mTouchResponseInterpolator =
+ new PathInterpolator(0.3f, 0f, 0.1f, 1f);
+
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
setWillNotDraw(!DEBUG);
@@ -939,7 +944,7 @@ public class NotificationPanelView extends PanelView implements
mQsExpansionFromOverscroll = false;
updateQsState();
}
- });
+ }, false /* isClick */);
}
private void onQsExpansionStarted() {
@@ -998,6 +1003,9 @@ public class NotificationPanelView extends PanelView implements
mAfforanceHelper.updatePreviews();
}
}
+ if (keyguardShowing) {
+ updateDozingVisibilities(false /* animate */);
+ }
resetVerticalPanelPosition();
updateQsState();
}
@@ -1387,10 +1395,11 @@ public class NotificationPanelView extends PanelView implements
}
private void flingSettings(float vel, boolean expand) {
- flingSettings(vel, expand, null);
+ flingSettings(vel, expand, null, false /* isClick */);
}
- private void flingSettings(float vel, boolean expand, final Runnable onFinishRunnable) {
+ private void flingSettings(float vel, boolean expand, final Runnable onFinishRunnable,
+ boolean isClick) {
float target = expand ? mQsMaxExpansionHeight : mQsMinExpansionHeight;
if (target == mQsExpansionHeight) {
mScrollYOverride = -1;
@@ -1405,7 +1414,12 @@ public class NotificationPanelView extends PanelView implements
}
mScrollView.setBlockFlinging(true);
ValueAnimator animator = ValueAnimator.ofFloat(mQsExpansionHeight, target);
- mFlingAnimationUtils.apply(animator, mQsExpansionHeight, target, vel);
+ if (isClick) {
+ animator.setInterpolator(mTouchResponseInterpolator);
+ animator.setDuration(368);
+ } else {
+ mFlingAnimationUtils.apply(animator, mQsExpansionHeight, target, vel);
+ }
if (belowFalsingThreshold) {
animator.setDuration(350);
}
@@ -1867,12 +1881,12 @@ public class NotificationPanelView extends PanelView implements
if (v == mHeader) {
onQsExpansionStarted();
if (mQsExpanded) {
- flingSettings(0 /* vel */, false /* expand */);
+ flingSettings(0 /* vel */, false /* expand */, null, true /* isClick */);
} else if (mQsExpansionEnabled) {
EventLogTags.writeSysuiLockscreenGesture(
EventLogConstants.SYSUI_TAP_TO_OPEN_QS,
0, 0);
- flingSettings(0 /* vel */, true /* expand */);
+ flingSettings(0 /* vel */, true /* expand */, null, true /* isClick */);
}
}
}
@@ -2109,6 +2123,12 @@ public class NotificationPanelView extends PanelView implements
public void setDozing(boolean dozing, boolean animate) {
if (dozing == mDozing) return;
mDozing = dozing;
+ if (mStatusBarState == StatusBarState.KEYGUARD) {
+ updateDozingVisibilities(animate);
+ }
+ }
+
+ private void updateDozingVisibilities(boolean animate) {
if (mDozing) {
mKeyguardStatusBar.setVisibility(View.INVISIBLE);
mKeyguardBottomArea.setVisibility(View.INVISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index d5209ea..54bd3e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -229,10 +229,6 @@ public class PanelBar extends FrameLayout {
public void onTrackingStarted(PanelView panel) {
mTracking = true;
- if (DEBUG && panel != mTouchingPanel) {
- LOG("shouldn't happen: onTrackingStarted(%s) != mTouchingPanel(%s)",
- panel, mTouchingPanel);
- }
}
public void onTrackingStopped(PanelView panel, boolean expand) {
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 7c7bec9..569b918 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -32,7 +32,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -345,8 +344,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private int mNavigationIconHints = 0;
private HandlerThread mHandlerThread;
- private AssistManager mAssistManager;
-
// ensure quick settings is disabled until the current user makes it through the setup wizard
private boolean mUserSetup = false;
private ContentObserver mUserSetupObserver = new ContentObserver(new Handler()) {
@@ -412,6 +409,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private boolean mWaitingForKeyguardExit;
private boolean mDozing;
+ private boolean mDozingRequested;
private boolean mScrimSrcModeEnabled;
private Interpolator mLinearInterpolator = new LinearInterpolator();
@@ -826,7 +824,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mAccessibilityController = new AccessibilityController(mContext);
mKeyguardBottomArea.setAccessibilityController(mAccessibilityController);
mNextAlarmController = new NextAlarmController(mContext);
- mKeyguardMonitor = new KeyguardMonitor();
+ mKeyguardMonitor = new KeyguardMonitor(mContext);
if (UserSwitcherController.isUserSwitcherAvailable(UserManager.get(mContext))) {
mUserSwitcherController = new UserSwitcherController(mContext, mKeyguardMonitor);
}
@@ -1153,7 +1151,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
if (shadeEntry == null) {
return;
}
- boolean isHeadsUped = mUseHeadsUp && shouldInterrupt(notification);
+ boolean isHeadsUped = mUseHeadsUp && shouldInterrupt(shadeEntry);
if (isHeadsUped) {
mHeadsUpManager.showNotification(shadeEntry);
// Mark as seen immediately
@@ -1171,6 +1169,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
notification.getKey());
notification.getNotification().fullScreenIntent.send();
+ shadeEntry.notifyFullScreenIntentLaunched();
} catch (PendingIntent.CanceledException e) {
}
}
@@ -2045,6 +2044,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION,
sbn.getKey());
notification.fullScreenIntent.send();
+ entry.entry.notifyFullScreenIntentLaunched();
} catch (PendingIntent.CanceledException e) {
}
}
@@ -2751,6 +2751,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
Runnable runnable = new Runnable() {
public void run() {
+ mAssistManager.hideAssist();
intent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
int result = ActivityManager.START_CANCELED;
@@ -2774,10 +2775,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
Runnable cancelRunnable = new Runnable() {
@Override
public void run() {
- callback.onActivityStarted(ActivityManager.START_CANCELED);
+ if (callback != null) {
+ callback.onActivityStarted(ActivityManager.START_CANCELED);
+ }
}
};
- executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShade, afterKeyguardGone);
+ executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShade,
+ afterKeyguardGone);
}
public void executeRunnableDismissingKeyguard(final Runnable runnable,
@@ -3164,9 +3168,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
(SignalClusterView) mKeyguardStatusBar.findViewById(R.id.signal_cluster);
final SignalClusterView signalClusterQs =
(SignalClusterView) mHeader.findViewById(R.id.signal_cluster);
- mNetworkController.addSignalCallback(signalCluster);
- mNetworkController.addSignalCallback(signalClusterKeyguard);
- mNetworkController.addSignalCallback(signalClusterQs);
+ mNetworkController.removeSignalCallback(signalCluster);
+ mNetworkController.removeSignalCallback(signalClusterKeyguard);
+ mNetworkController.removeSignalCallback(signalClusterQs);
+ if (mQSPanel != null && mQSPanel.getHost() != null) {
+ mQSPanel.getHost().destroy();
+ }
}
private boolean mDemoModeAllowed;
@@ -3473,9 +3480,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
private void updateDozingState() {
- if (mState != StatusBarState.KEYGUARD && !mNotificationPanel.isDozing()) {
- return;
- }
boolean animate = !mDozing && mDozeScrimController.isPulsing();
mNotificationPanel.setDozing(mDozing, animate);
mStackScroller.setDark(mDozing, animate, mScreenOnTouchLocation);
@@ -3592,6 +3596,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mState = state;
mGroupManager.setStatusBarState(state);
mStatusBarWindowManager.setStatusBarState(state);
+ updateDozing();
}
@Override
@@ -3907,6 +3912,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
}
+ private void updateDozing() {
+ mDozing = mDozingRequested && mState == StatusBarState.KEYGUARD;
+ updateDozingState();
+ }
+
private final class ShadeUpdates {
private final ArraySet<String> mVisibleNotifications = new ArraySet<String>();
private final ArraySet<String> mNewVisibleNotifications = new ArraySet<String>();
@@ -4012,10 +4022,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
private void handleStartDozing(@NonNull Runnable ready) {
- if (!mDozing) {
- mDozing = true;
+ if (!mDozingRequested) {
+ mDozingRequested = true;
DozeLog.traceDozing(mContext, mDozing);
- updateDozingState();
+ updateDozing();
}
ready.run();
}
@@ -4025,10 +4035,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
private void handleStopDozing() {
- if (mDozing) {
- mDozing = false;
+ if (mDozingRequested) {
+ mDozingRequested = false;
DozeLog.traceDozing(mContext, mDozing);
- updateDozingState();
+ updateDozing();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 0872e06..6a6266e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -162,7 +162,8 @@ public class PhoneStatusBarPolicy {
mCast.addCallback(mCastCallback);
// hotspot
- mService.setIcon(SLOT_HOTSPOT, R.drawable.stat_sys_hotspot, 0, null);
+ mService.setIcon(SLOT_HOTSPOT, R.drawable.stat_sys_hotspot, 0,
+ mContext.getString(R.string.accessibility_status_bar_hotspot));
mService.setIconVisibility(SLOT_HOTSPOT, mHotspot.isHotspotEnabled());
mHotspot.addCallback(mHotspotCallback);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 0ef0fd9..25a93dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -19,13 +19,9 @@ package com.android.systemui.statusbar.phone;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Process;
-import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
-import android.provider.Settings.Secure;
+import android.os.Process;
import android.util.Log;
import com.android.systemui.R;
@@ -35,25 +31,26 @@ import com.android.systemui.qs.tiles.BluetoothTile;
import com.android.systemui.qs.tiles.CastTile;
import com.android.systemui.qs.tiles.CellularTile;
import com.android.systemui.qs.tiles.ColorInversionTile;
+import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.FlashlightTile;
import com.android.systemui.qs.tiles.HotspotTile;
import com.android.systemui.qs.tiles.IntentTile;
import com.android.systemui.qs.tiles.LocationTile;
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.qs.tiles.WifiTile;
-import com.android.systemui.qs.tiles.DndTile;
-import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.FlashlightController;
+import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
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.HotspotController;
import com.android.systemui.statusbar.policy.SecurityController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
import java.util.ArrayList;
import java.util.Arrays;
@@ -63,7 +60,7 @@ import java.util.List;
import java.util.Map;
/** Platform implementation of the quick settings tile host **/
-public class QSTileHost implements QSTile.Host {
+public class QSTileHost implements QSTile.Host, Tunable {
private static final String TAG = "QSTileHost";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -72,8 +69,7 @@ public class QSTileHost implements QSTile.Host {
private final Context mContext;
private final PhoneStatusBar mStatusBar;
private final LinkedHashMap<String, QSTile<?>> mTiles = new LinkedHashMap<>();
- private final ArrayList<String> mTileSpecs = new ArrayList<>();
- private final Observer mObserver = new Observer();
+ protected final ArrayList<String> mTileSpecs = new ArrayList<>();
private final BluetoothController mBluetooth;
private final LocationController mLocation;
private final RotationLockController mRotation;
@@ -82,7 +78,6 @@ public class QSTileHost implements QSTile.Host {
private final HotspotController mHotspot;
private final CastController mCast;
private final Looper mLooper;
- protected final CurrentUserTracker mUserTracker;
private final FlashlightController mFlashlight;
private final UserSwitcherController mUserSwitcherController;
private final KeyguardMonitor mKeyguard;
@@ -116,22 +111,11 @@ public class QSTileHost implements QSTile.Host {
ht.start();
mLooper = ht.getLooper();
- mUserTracker = new CurrentUserTracker(mContext) {
- @Override
- public void onUserSwitched(int newUserId) {
- recreateTiles();
- for (QSTile<?> tile : mTiles.values()) {
- tile.userSwitch(newUserId);
- }
- mSecurity.onUserSwitched(newUserId);
- mNetwork.onUserSwitched(newUserId);
- mObserver.register();
- }
- };
- recreateTiles();
+ TunerService.get(mContext).addTunable(this, TILES_SETTING);
+ }
- mUserTracker.startTracking();
- mObserver.register();
+ public void destroy() {
+ TunerService.get(mContext).removeTunable(this);
}
@Override
@@ -221,10 +205,14 @@ public class QSTileHost implements QSTile.Host {
public SecurityController getSecurityController() {
return mSecurity;
}
-
- private void recreateTiles() {
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (!TILES_SETTING.equals(key)) {
+ return;
+ }
if (DEBUG) Log.d(TAG, "Recreating tiles");
- final List<String> tileSpecs = loadTileSpecs();
+ final List<String> tileSpecs = loadTileSpecs(newValue);
if (tileSpecs.equals(mTileSpecs)) return;
for (Map.Entry<String, QSTile<?>> tile : mTiles.entrySet()) {
if (!tileSpecs.contains(tile.getKey())) {
@@ -270,11 +258,9 @@ public class QSTileHost implements QSTile.Host {
else throw new IllegalArgumentException("Bad tile spec: " + tileSpec);
}
- protected List<String> loadTileSpecs() {
+ protected List<String> loadTileSpecs(String tileList) {
final Resources res = mContext.getResources();
final String defaultTileList = res.getString(R.string.quick_settings_tiles_default);
- String tileList = Secure.getStringForUser(mContext.getContentResolver(), TILES_SETTING,
- mUserTracker.getCurrentUserId());
if (tileList == null) {
tileList = res.getString(R.string.quick_settings_tiles);
if (DEBUG) Log.d(TAG, "Loaded tile specs from config: " + tileList);
@@ -297,26 +283,4 @@ public class QSTileHost implements QSTile.Host {
}
return tiles;
}
-
- private class Observer extends ContentObserver {
- private boolean mRegistered;
-
- public Observer() {
- super(new Handler(Looper.getMainLooper()));
- }
-
- public void register() {
- if (mRegistered) {
- mContext.getContentResolver().unregisterContentObserver(this);
- }
- mContext.getContentResolver().registerContentObserver(Secure.getUriFor(TILES_SETTING),
- false, this, mUserTracker.getCurrentUserId());
- mRegistered = true;
- }
-
- @Override
- public void onChange(boolean selfChange, Uri uri) {
- recreateTiles();
- }
- }
}
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 181926c..dfc6924 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -110,7 +110,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private NextAlarmController mNextAlarmController;
private QSPanel mQSPanel;
-
private final Rect mClipBounds = new Rect();
private boolean mCaptureValues;
@@ -121,6 +120,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
private float mCurrentT;
private boolean mShowingDetail;
+ private boolean mDetailTransitioning;
public StatusBarHeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -623,7 +623,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
mSettingsButton.setTranslationX(values.settingsTranslation);
mSettingsButton.setRotation(values.settingsRotation);
applyAlpha(mEmergencyCallsOnly, values.emergencyCallsOnlyAlpha);
- if (!mShowingDetail) {
+ if (!mShowingDetail && !mDetailTransitioning) {
// Otherwise it needs to stay invisible
applyAlpha(mAlarmStatus, values.alarmStatusAlpha);
}
@@ -706,6 +706,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
@Override
public void onShowingDetail(final QSTile.DetailAdapter detail) {
+ mDetailTransitioning = true;
post(new Runnable() {
@Override
public void run() {
@@ -788,6 +789,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL
if (!in) {
v.setVisibility(INVISIBLE);
}
+ mDetailTransitioning = false;
}
})
.start();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index a268077..067e50e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -20,12 +20,10 @@ import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
-import android.database.ContentObserver;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
-import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
import android.view.View;
@@ -44,6 +42,8 @@ import com.android.systemui.R;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerService.Tunable;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -53,7 +53,7 @@ import java.util.ArrayList;
* limited to: notification icons, signal cluster, additional status icons, and clock in the status
* bar.
*/
-public class StatusBarIconController {
+public class StatusBarIconController implements Tunable {
public static final long DEFAULT_TINT_ANIMATION_DURATION = 120;
@@ -95,7 +95,7 @@ public class StatusBarIconController {
private long mTransitionDeferringStartTime;
private long mTransitionDeferringDuration;
- private final ArraySet<String> mIconBlacklist;
+ private final ArraySet<String> mIconBlacklist = new ArraySet<>();
private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
@Override
@@ -126,14 +126,33 @@ public class StatusBarIconController {
mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
mHandler = new Handler();
- mIconBlacklist = getIconBlacklist(context);
updateResources();
- context.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(StatusBarIconController.ICON_BLACKLIST), false,
- mBlacklistObserver);
+ TunerService.get(mContext).addTunable(this, ICON_BLACKLIST);
}
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (!ICON_BLACKLIST.equals(key)) {
+ return;
+ }
+ mIconBlacklist.clear();
+ mIconBlacklist.addAll(getIconBlacklist(newValue));
+ ArrayList<StatusBarIconView> views = new ArrayList<StatusBarIconView>();
+ // Get all the current views.
+ for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
+ views.add((StatusBarIconView) mStatusIcons.getChildAt(i));
+ }
+ // Remove all the icons.
+ for (int i = views.size() - 1; i >= 0; i--) {
+ removeSystemIcon(views.get(i).getSlot(), i, i);
+ }
+ // Add them all back
+ for (int i = 0; i < views.size(); i++) {
+ addSystemIcon(views.get(i).getSlot(), i, i, views.get(i).getStatusBarIcon());
+ }
+ };
+
public void updateResources() {
mIconSize = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_icon_size);
@@ -429,29 +448,7 @@ public class StatusBarIconController {
mTransitionPending = false;
}
- private final ContentObserver mBlacklistObserver = new ContentObserver(new Handler()) {
- public void onChange(boolean selfChange) {
- mIconBlacklist.clear();
- mIconBlacklist.addAll(getIconBlacklist(mContext));
- ArrayList<StatusBarIconView> views = new ArrayList<StatusBarIconView>();
- // Get all the current views.
- for (int i = 0; i < mStatusIcons.getChildCount(); i++) {
- views.add((StatusBarIconView) mStatusIcons.getChildAt(i));
- }
- // Remove all the icons.
- for (int i = views.size() - 1; i >= 0; i--) {
- removeSystemIcon(views.get(i).getSlot(), i, i);
- }
- // Add them all back
- for (int i = 0; i < views.size(); i++) {
- addSystemIcon(views.get(i).getSlot(), i, i, views.get(i).getStatusBarIcon());
- }
- }
- };
-
- public static ArraySet<String> getIconBlacklist(Context context) {
- String blackListStr = Settings.Secure.getString(context.getContentResolver(),
- ICON_BLACKLIST);
+ public static ArraySet<String> getIconBlacklist(String blackListStr) {
ArraySet<String> ret = new ArraySet<String>();
if (blackListStr != null) {
String[] blacklist = blackListStr.split(",");
@@ -463,8 +460,4 @@ public class StatusBarIconController {
}
return ret;
}
-
- public static boolean isBlocked(Context context, String slot) {
- return getIconBlacklist(context).contains(slot);
- }
}
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 6cb890a..fcf3a9c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -447,4 +447,12 @@ public class StatusBarKeyguardViewManager {
mPhoneStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */,
false /* delayed */, speedUpFactor);
}
+
+ /**
+ * Notifies that the user has authenticated by other means than using the bouncer, for example,
+ * fingerprint.
+ */
+ public void notifyKeyguardAuthenticated() {
+ mBouncer.notifyKeyguardAuthenticated();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index 0b3575f..d4eb553 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -16,21 +16,59 @@
package com.android.systemui.statusbar.policy;
+import android.app.ActivityManager;
+import android.content.Context;
+
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.settings.CurrentUserTracker;
+
import java.util.ArrayList;
-public final class KeyguardMonitor {
+public final class KeyguardMonitor extends KeyguardUpdateMonitorCallback {
private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
+ private final Context mContext;
+ private final CurrentUserTracker mUserTracker;
+ private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+
+ private int mCurrentUser;
private boolean mShowing;
private boolean mSecure;
+ private boolean mTrusted;
+
+ private boolean mListening;
+
+ public KeyguardMonitor(Context context) {
+ mContext = context;
+ mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+ mUserTracker = new CurrentUserTracker(mContext) {
+ @Override
+ public void onUserSwitched(int newUserId) {
+ mCurrentUser = newUserId;
+ updateTrustedState();
+ }
+ };
+ }
public void addCallback(Callback callback) {
mCallbacks.add(callback);
+ if (mCallbacks.size() != 0 && !mListening) {
+ mListening = true;
+ mCurrentUser = ActivityManager.getCurrentUser();
+ updateTrustedState();
+ mKeyguardUpdateMonitor.registerCallback(this);
+ mUserTracker.startTracking();
+ }
}
public void removeCallback(Callback callback) {
- mCallbacks.remove(callback);
+ if (mCallbacks.remove(callback) && mCallbacks.size() == 0 && mListening) {
+ mListening = false;
+ mKeyguardUpdateMonitor.removeCallback(this);
+ mUserTracker.stopTracking();
+ }
}
public boolean isShowing() {
@@ -41,10 +79,28 @@ public final class KeyguardMonitor {
return mSecure;
}
+ public boolean isTrusted() {
+ return mTrusted;
+ }
+
public void notifyKeyguardState(boolean showing, boolean secure) {
if (mShowing == showing && mSecure == secure) return;
mShowing = showing;
mSecure = secure;
+ notifyKeyguardChanged();
+ }
+
+ @Override
+ public void onTrustChanged(int userId) {
+ updateTrustedState();
+ notifyKeyguardChanged();
+ }
+
+ private void updateTrustedState() {
+ mTrusted = mKeyguardUpdateMonitor.getUserHasTrust(mCurrentUser);
+ }
+
+ private void notifyKeyguardChanged() {
for (Callback callback : mCallbacks) {
callback.onKeyguardChanged();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index ad27c6e..41fc967 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -411,7 +411,8 @@ public class UserSwitcherController {
@Override
public int getCount() {
boolean secureKeyguardShowing = mController.mKeyguardMonitor.isShowing()
- && mController.mKeyguardMonitor.isSecure();
+ && mController.mKeyguardMonitor.isSecure()
+ && !mController.mKeyguardMonitor.isTrusted();
if (!secureKeyguardShowing) {
return mController.mUsers.size();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index eac5e79..c31244c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -96,6 +96,7 @@ public class StackStateAnimator {
private ExpandableNotificationRow mChildExpandingView;
private int mHeadsUpAppearHeightBottom;
private boolean mShadeExpanded;
+ private ArrayList<View> mChildrenToClearFromOverlay = new ArrayList<>();
public StackStateAnimator(NotificationStackScrollLayout hostLayout) {
mHostLayout = hostLayout;
@@ -794,6 +795,10 @@ public class StackStateAnimator {
private void onAnimationFinished() {
mHostLayout.onChildAnimationFinished();
+ for (View v : mChildrenToClearFromOverlay) {
+ mHostLayout.getOverlay().remove(v);
+ }
+ mChildrenToClearFromOverlay.clear();
}
/**
@@ -880,8 +885,20 @@ public class StackStateAnimator {
finalState.applyState(changingView, mTmpState);
} else if (event.animationType == NotificationStackScrollLayout
.AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR) {
- // This item is added, initialize it's properties.
mHeadsUpDisappearChildren.add(changingView);
+ if (mHostLayout.indexOfChild(changingView) == -1) {
+ // This notification was actually removed, so we need to add it to the overlay
+ mHostLayout.getOverlay().add(changingView);
+ ViewState viewState = new ViewState();
+ viewState.initFrom(changingView);
+ viewState.yTranslation = -changingView.getActualHeight();
+ // We temporarily enable Y animations, the real filter will be combined
+ // afterwards anyway
+ mAnimationFilter.animateY = true;
+ startViewAnimations(changingView, viewState, 0,
+ ANIMATION_DURATION_HEADS_UP_DISAPPEAR);
+ mChildrenToClearFromOverlay.add(changingView);
+ }
}
mNewEvents.add(event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
new file mode 100644
index 0000000..d9f0598
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2015 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.tuner;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
+import android.preference.SwitchPreference;
+import android.provider.Settings;
+
+import com.android.systemui.DemoMode;
+import com.android.systemui.R;
+
+public class DemoModeFragment extends PreferenceFragment implements OnPreferenceChangeListener {
+
+ private static final String DEMO_MODE_ALLOWED = "sysui_demo_allowed";
+ private static final String DEMO_MODE_ON = "sysui_tuner_demo_on";
+
+ private static final String[] STATUS_ICONS = {
+ "volume",
+ "bluetooth",
+ "location",
+ "alarm",
+ "zen",
+ "sync",
+ "tty",
+ "eri",
+ "mute",
+ "speakerphone",
+ "managed_profile",
+ };
+
+ private SwitchPreference mEnabledSwitch;
+ private SwitchPreference mOnSwitch;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Context context = getContext();
+ mEnabledSwitch = new SwitchPreference(context);
+ mEnabledSwitch.setTitle(R.string.enable_demo_mode);
+ mEnabledSwitch.setOnPreferenceChangeListener(this);
+ mOnSwitch = new SwitchPreference(context);
+ mOnSwitch.setTitle(R.string.show_demo_mode);
+ mOnSwitch.setEnabled(false);
+ mOnSwitch.setOnPreferenceChangeListener(this);
+
+ PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(context);
+ screen.addPreference(mEnabledSwitch);
+ screen.addPreference(mOnSwitch);
+ setPreferenceScreen(screen);
+
+ updateDemoModeEnabled();
+ updateDemoModeOn();
+ ContentResolver contentResolver = getContext().getContentResolver();
+ contentResolver.registerContentObserver(Settings.Global.getUriFor(DEMO_MODE_ALLOWED), false,
+ mDemoModeObserver);
+ contentResolver.registerContentObserver(Settings.Global.getUriFor(DEMO_MODE_ON), false,
+ mDemoModeObserver);
+ }
+
+ @Override
+ public void onDestroy() {
+ getContext().getContentResolver().unregisterContentObserver(mDemoModeObserver);
+ super.onDestroy();
+ }
+
+ private void updateDemoModeEnabled() {
+ boolean enabled = Settings.Global.getInt(getContext().getContentResolver(),
+ DEMO_MODE_ALLOWED, 0) != 0;
+ mEnabledSwitch.setChecked(enabled);
+ mOnSwitch.setEnabled(enabled);
+ }
+
+ private void updateDemoModeOn() {
+ boolean enabled = Settings.Global.getInt(getContext().getContentResolver(),
+ DEMO_MODE_ON, 0) != 0;
+ mOnSwitch.setChecked(enabled);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (preference == mEnabledSwitch) {
+ setGlobal(DEMO_MODE_ALLOWED, newValue == Boolean.TRUE ? 1 : 0);
+ } else if (preference == mOnSwitch) {
+ if (newValue == Boolean.TRUE) {
+ startDemoMode();
+ } else {
+ stopDemoMode();
+ }
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ private void startDemoMode() {
+ Intent intent = new Intent(DemoMode.ACTION_DEMO);
+
+ intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_ENTER);
+ getContext().sendBroadcast(intent);
+
+ intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_CLOCK);
+ intent.putExtra("hhmm", "0520");
+ getContext().sendBroadcast(intent);
+
+ intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_NETWORK);
+ intent.putExtra("wifi", "show");
+ intent.putExtra("mobile", "show");
+ intent.putExtra("sims", "1");
+ intent.putExtra("nosim", "false");
+ intent.putExtra("fully", "true");
+ intent.putExtra("level", "4");
+ intent.putExtra("datatypel", "");
+ getContext().sendBroadcast(intent);
+
+ intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_BATTERY);
+ intent.putExtra("level", "100");
+ intent.putExtra("plugged", "false");
+ getContext().sendBroadcast(intent);
+
+ intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_STATUS);
+ for (String icon : STATUS_ICONS) {
+ intent.putExtra(icon, "hide");
+ }
+ getContext().sendBroadcast(intent);
+
+ intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_NOTIFICATIONS);
+ intent.putExtra("visible", "false");
+ getContext().sendBroadcast(intent);
+
+ setGlobal(DEMO_MODE_ON, 1);
+ }
+
+ private void stopDemoMode() {
+ Intent intent = new Intent(DemoMode.ACTION_DEMO);
+ intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_EXIT);
+ getContext().sendBroadcast(intent);
+ setGlobal(DEMO_MODE_ON, 0);
+ }
+
+ private void setGlobal(String key, int value) {
+ Settings.Global.putInt(getContext().getContentResolver(), key, value);
+ }
+
+ private final ContentObserver mDemoModeObserver =
+ new ContentObserver(new Handler(Looper.getMainLooper())) {
+ public void onChange(boolean selfChange) {
+ updateDemoModeEnabled();
+ updateDemoModeOn();
+ };
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
index 9f593fc..7472af9 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java
@@ -15,6 +15,7 @@
*/
package com.android.systemui.tuner;
+import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.ClipData;
@@ -49,6 +50,7 @@ import com.android.systemui.qs.tiles.IntentTile;
import com.android.systemui.statusbar.phone.QSTileHost;
import com.android.systemui.statusbar.policy.SecurityController;
+import java.util.ArrayList;
import java.util.List;
public class QsTuner extends Fragment implements Callback {
@@ -107,6 +109,12 @@ public class QsTuner extends Fragment implements Callback {
return mScrollRoot;
}
+ @Override
+ public void onDestroyView() {
+ mTileHost.destroy();
+ super.onDestroyView();
+ }
+
private void setupDropTarget() {
QSTileView tileView = new QSTileView(getContext());
QSTile.State state = new QSTile.State();
@@ -187,7 +195,7 @@ public class QsTuner extends Fragment implements Callback {
if (oldTile.equals(newTile)) {
return;
}
- List<String> order = loadTileSpecs();
+ List<String> order = new ArrayList<>(mTileSpecs);
int index = order.indexOf(oldTile);
if (index < 0) {
Log.e(TAG, "Can't find " + oldTile);
@@ -199,32 +207,33 @@ public class QsTuner extends Fragment implements Callback {
}
public void remove(String tile) {
- List<String> tiles = loadTileSpecs();
+ List<String> tiles = new ArrayList<>(mTileSpecs);
tiles.remove(tile);
setTiles(tiles);
}
public void add(String tile) {
- List<String> tiles = loadTileSpecs();
+ List<String> tiles = new ArrayList<>(mTileSpecs);
tiles.add(tile);
setTiles(tiles);
}
public void reset() {
Secure.putStringForUser(getContext().getContentResolver(),
- TILES_SETTING, "default", mUserTracker.getCurrentUserId());
+ TILES_SETTING, "default", ActivityManager.getCurrentUser());
}
private void setTiles(List<String> tiles) {
Secure.putStringForUser(getContext().getContentResolver(), TILES_SETTING,
- TextUtils.join(",", tiles), mUserTracker.getCurrentUserId());
+ TextUtils.join(",", tiles), ActivityManager.getCurrentUser());
}
public void showAddDialog() {
- List<String> tiles = loadTileSpecs();
+ List<String> tiles = mTileSpecs;
String[] defaults =
getContext().getString(R.string.quick_settings_tiles_default).split(",");
final String[] available = new String[defaults.length + 1 - tiles.size()];
+ final String[] availableTiles = new String[available.length];
int index = 0;
for (int i = 0; i < defaults.length; i++) {
if (tiles.contains(defaults[i])) {
@@ -232,8 +241,10 @@ public class QsTuner extends Fragment implements Callback {
}
int resource = getLabelResource(defaults[i]);
if (resource != 0) {
+ availableTiles[index] = defaults[i];
available[index++] = getContext().getString(resource);
} else {
+ availableTiles[index] = defaults[i];
available[index++] = defaults[i];
}
}
@@ -243,7 +254,7 @@ public class QsTuner extends Fragment implements Callback {
.setItems(available, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (which < available.length - 1) {
- add(available[which]);
+ add(availableTiles[which]);
} else {
showBroadcastTileDialog();
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
index 8158a68..d4cc56d 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java
@@ -15,6 +15,7 @@
*/
package com.android.systemui.tuner;
+import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.preference.SwitchPreference;
@@ -23,28 +24,38 @@ import android.text.TextUtils;
import android.util.AttributeSet;
import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.tuner.TunerService.Tunable;
import java.util.Set;
-public class StatusBarSwitch extends SwitchPreference {
+public class StatusBarSwitch extends SwitchPreference implements Tunable {
+
+ private Set<String> mBlacklist;
public StatusBarSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
- setChecked(!StatusBarIconController.isBlocked(getContext(), getKey()));
+ }
+
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (!StatusBarIconController.ICON_BLACKLIST.equals(key)) {
+ return;
+ }
+ mBlacklist = StatusBarIconController.getIconBlacklist(newValue);
+ setChecked(!mBlacklist.contains(getKey()));
}
@Override
protected boolean persistBoolean(boolean value) {
- Set<String> blacklist = StatusBarIconController.getIconBlacklist(getContext());
if (!value) {
// If not enabled add to blacklist.
- if (!blacklist.contains(getKey())) {
- blacklist.add(getKey());
- setList(blacklist);
+ if (!mBlacklist.contains(getKey())) {
+ mBlacklist.add(getKey());
+ setList(mBlacklist);
}
} else {
- if (blacklist != null && blacklist.remove(getKey())) {
- setList(blacklist);
+ if (mBlacklist.remove(getKey())) {
+ setList(mBlacklist);
}
}
return true;
@@ -52,7 +63,7 @@ public class StatusBarSwitch extends SwitchPreference {
private void setList(Set<String> blacklist) {
ContentResolver contentResolver = getContext().getContentResolver();
- Settings.Secure.putString(contentResolver, StatusBarIconController.ICON_BLACKLIST,
- TextUtils.join(",", blacklist));
+ Settings.Secure.putStringForUser(contentResolver, StatusBarIconController.ICON_BLACKLIST,
+ TextUtils.join(",", blacklist), ActivityManager.getCurrentUser());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index b40adaf..4a8c2e4 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -26,15 +26,19 @@ import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceFragment;
+import android.preference.PreferenceGroup;
import android.preference.SwitchPreference;
import android.provider.Settings.System;
import android.view.MenuItem;
import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.tuner.TunerService.Tunable;
public class TunerFragment extends PreferenceFragment {
private static final String KEY_QS_TUNER = "qs_tuner";
+ private static final String KEY_DEMO_MODE = "demo_mode";
private static final String KEY_BATTERY_PCT = "battery_pct";
private final SettingObserver mSettingObserver = new SettingObserver();
@@ -55,7 +59,17 @@ public class TunerFragment extends PreferenceFragment {
ft.replace(android.R.id.content, new QsTuner(), "QsTuner");
ft.addToBackStack(null);
ft.commit();
- return false;
+ return true;
+ }
+ });
+ findPreference(KEY_DEMO_MODE).setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ FragmentTransaction ft = getFragmentManager().beginTransaction();
+ ft.replace(android.R.id.content, new DemoModeFragment(), "DemoMode");
+ ft.addToBackStack(null);
+ ft.commit();
+ return true;
}
});
mBatteryPct = (SwitchPreference) findPreference(KEY_BATTERY_PCT);
@@ -67,12 +81,42 @@ public class TunerFragment extends PreferenceFragment {
updateBatteryPct();
getContext().getContentResolver().registerContentObserver(
System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
+
+ registerPrefs(getPreferenceScreen());
}
@Override
public void onPause() {
super.onPause();
getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
+
+ unregisterPrefs(getPreferenceScreen());
+ }
+
+ private void registerPrefs(PreferenceGroup group) {
+ TunerService tunerService = TunerService.get(getContext());
+ final int N = group.getPreferenceCount();
+ for (int i = 0; i < N; i++) {
+ Preference pref = group.getPreference(i);
+ if (pref instanceof StatusBarSwitch) {
+ tunerService.addTunable((Tunable) pref, StatusBarIconController.ICON_BLACKLIST);
+ } else if (pref instanceof PreferenceGroup) {
+ registerPrefs((PreferenceGroup) pref);
+ }
+ }
+ }
+
+ private void unregisterPrefs(PreferenceGroup group) {
+ TunerService tunerService = TunerService.get(getContext());
+ final int N = group.getPreferenceCount();
+ for (int i = 0; i < N; i++) {
+ Preference pref = group.getPreference(i);
+ if (pref instanceof Tunable) {
+ tunerService.removeTunable((Tunable) pref);
+ } else if (pref instanceof PreferenceGroup) {
+ registerPrefs((PreferenceGroup) pref);
+ }
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
new file mode 100644
index 0000000..de5aaf6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2015 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.tuner;
+
+import android.app.ActivityManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.util.ArrayMap;
+
+import com.android.systemui.SystemUI;
+import com.android.systemui.SystemUIApplication;
+import com.android.systemui.settings.CurrentUserTracker;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+
+public class TunerService extends SystemUI {
+
+ private final Observer mObserver = new Observer();
+ // Map of Uris we listen on to their settings keys.
+ private final ArrayMap<Uri, String> mListeningUris = new ArrayMap<>();
+ // Map of settings keys to the listener.
+ private final HashMap<String, List<Tunable>> mTunableLookup = new HashMap<>();
+
+ private ContentResolver mContentResolver;
+ private int mCurrentUser;
+ private CurrentUserTracker mUserTracker;
+
+ @Override
+ public void start() {
+ mContentResolver = mContext.getContentResolver();
+ putComponent(TunerService.class, this);
+
+ mCurrentUser = ActivityManager.getCurrentUser();
+ mUserTracker = new CurrentUserTracker(mContext) {
+ @Override
+ public void onUserSwitched(int newUserId) {
+ mCurrentUser = newUserId;
+ reloadAll();
+ reregisterAll();
+ }
+ };
+ mUserTracker.startTracking();
+ }
+
+ public void addTunable(Tunable tunable, String... keys) {
+ for (String key : keys) {
+ addTunable(tunable, key);
+ }
+ }
+
+ private void addTunable(Tunable tunable, String key) {
+ if (!mTunableLookup.containsKey(key)) {
+ mTunableLookup.put(key, new ArrayList<Tunable>());
+ }
+ mTunableLookup.get(key).add(tunable);
+ Uri uri = Settings.Secure.getUriFor(key);
+ if (!mListeningUris.containsKey(uri)) {
+ mListeningUris.put(uri, key);
+ mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
+ }
+ // Send the first state.
+ String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
+ tunable.onTuningChanged(key, value);
+ }
+
+ public void removeTunable(Tunable tunable) {
+ for (List<Tunable> list : mTunableLookup.values()) {
+ list.remove(tunable);
+ }
+ }
+
+ protected void reregisterAll() {
+ if (mListeningUris.size() == 0) {
+ return;
+ }
+ mContentResolver.unregisterContentObserver(mObserver);
+ for (Uri uri : mListeningUris.keySet()) {
+ mContentResolver.registerContentObserver(uri, false, mObserver, mCurrentUser);
+ }
+ }
+
+ public void reloadSetting(Uri uri) {
+ String key = mListeningUris.get(uri);
+ String value = Settings.Secure.getStringForUser(mContentResolver, key, mCurrentUser);
+ for (Tunable tunable : mTunableLookup.get(key)) {
+ tunable.onTuningChanged(key, value);
+ }
+ }
+
+ private void reloadAll() {
+ for (String key : mTunableLookup.keySet()) {
+ String value = Settings.Secure.getStringForUser(mContentResolver, key,
+ mCurrentUser);
+ for (Tunable tunable : mTunableLookup.get(key)) {
+ tunable.onTuningChanged(key, value);
+ }
+ }
+ }
+
+ // Only used in other processes, such as the tuner.
+ private static TunerService sInstance;
+
+ public static TunerService get(Context context) {
+ SystemUIApplication sysUi = (SystemUIApplication) context.getApplicationContext();
+ TunerService service = sysUi.getComponent(TunerService.class);
+ if (service == null) {
+ // Can't get it as a component, must in the tuner, lets just create one for now.
+ return getStaticService(context);
+ }
+ return service;
+ }
+
+ private static TunerService getStaticService(Context context) {
+ if (sInstance == null) {
+ sInstance = new TunerService();
+ sInstance.mContext = context.getApplicationContext();
+ sInstance.mComponents = new HashMap<>();
+ sInstance.start();
+ }
+ return sInstance;
+ }
+
+ private class Observer extends ContentObserver {
+ public Observer() {
+ super(new Handler(Looper.getMainLooper()));
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ if (userId == ActivityManager.getCurrentUser()) {
+ reloadSetting(uri);
+ }
+ }
+ }
+
+ public interface Tunable {
+ void onTuningChanged(String key, String newValue);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java b/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java
index f7cb9fe..81461bd 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/SegmentedButtons.java
@@ -36,6 +36,7 @@ public class SegmentedButtons extends LinearLayout {
private final Context mContext;
private final LayoutInflater mInflater;
+ private final SpTexts mSpTexts;
private Callback mCallback;
private Object mSelectedValue;
@@ -45,6 +46,7 @@ public class SegmentedButtons extends LinearLayout {
mContext = context;
mInflater = LayoutInflater.from(mContext);
setOrientation(HORIZONTAL);
+ mSpTexts = new SpTexts(mContext);
}
public void setCallback(Callback callback) {
@@ -68,10 +70,11 @@ public class SegmentedButtons extends LinearLayout {
fireOnSelected();
}
- public void addButton(int labelResId, Object value) {
+ public void addButton(int labelResId, int contentDescriptionResId, Object value) {
final Button b = (Button) mInflater.inflate(R.layout.segmented_button, this, false);
b.setTag(LABEL_RES_KEY, labelResId);
b.setText(labelResId);
+ b.setContentDescription(getResources().getString(contentDescriptionResId));
final LayoutParams lp = (LayoutParams) b.getLayoutParams();
if (getChildCount() == 0) {
lp.leftMargin = lp.rightMargin = 0; // first button has no margin
@@ -86,6 +89,7 @@ public class SegmentedButtons extends LinearLayout {
fireInteraction();
}
});
+ mSpTexts.add(b);
}
public void updateLocale() {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index 310a64c..29bea4d 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -386,18 +386,8 @@ public class VolumeDialog {
}
}
} else {
- if (mAutomute && !row.ss.muteSupported) {
- final boolean vmute = row.ss.level == 0;
- mController.setStreamVolume(stream, vmute ? row.lastAudibleLevel : 0);
- } else {
- final boolean mute = !row.ss.muted;
- mController.setStreamMute(stream, mute);
- if (mAutomute) {
- if (!mute && row.ss.level == 0) {
- mController.setStreamVolume(stream, 1);
- }
- }
- }
+ final boolean vmute = row.ss.level == 0;
+ mController.setStreamVolume(stream, vmute ? row.lastAudibleLevel : 0);
}
row.userAttempt = 0; // reset the grace period, slider should update immediately
}
@@ -589,6 +579,9 @@ public class VolumeDialog {
if (ss.level > 0) {
row.lastAudibleLevel = ss.level;
}
+ if (ss.level == row.requestedLevel) {
+ row.requestedLevel = -1;
+ }
final boolean isRingStream = row.stream == AudioManager.STREAM_RING;
final boolean isSystemStream = row.stream == AudioManager.STREAM_SYSTEM;
final boolean isAlarmStream = row.stream == AudioManager.STREAM_ALARM;
@@ -664,7 +657,10 @@ public class VolumeDialog {
row.icon.setContentDescription(ss.name);
// update slider
- updateVolumeRowSliderH(row, zenMuted);
+ final boolean enableSlider = !zenMuted;
+ final int vlevel = row.ss.muted && (isRingVibrate || !isRingStream && !zenMuted) ? 0
+ : row.ss.level;
+ updateVolumeRowSliderH(row, enableSlider, vlevel);
}
private void updateVolumeRowSliderTintH(VolumeRow row, boolean isActive) {
@@ -676,8 +672,8 @@ public class VolumeDialog {
row.slider.setThumbTintList(tint);
}
- private void updateVolumeRowSliderH(VolumeRow row, boolean zenMuted) {
- row.slider.setEnabled(!zenMuted);
+ private void updateVolumeRowSliderH(VolumeRow row, boolean enable, int vlevel) {
+ row.slider.setEnabled(enable);
updateVolumeRowSliderTintH(row, row.stream == mActiveStream);
if (row.tracking) {
return; // don't update if user is sliding
@@ -694,7 +690,6 @@ public class VolumeDialog {
row.userAttempt + USER_ATTEMPT_GRACE_PERIOD);
return; // don't update if visible and in grace period
}
- final int vlevel = row.ss.muted ? 0 : row.ss.level;
if (vlevel == level) {
if (mShowing && rowVisible) {
return; // don't clamp if visible
@@ -1018,7 +1013,7 @@ public class VolumeDialog {
private StreamState ss;
private long userAttempt; // last user-driven slider change
private boolean tracking; // tracking slider touch
- private int requestedLevel;
+ private int requestedLevel = -1; // pending user-requested level via progress changed
private int iconRes;
private int iconMuteRes;
private boolean important;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index 027d637..ced1a3c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -89,6 +89,7 @@ public class ZenModePanel extends LinearLayout {
private final IconPulser mIconPulser;
private final TransitionHelper mTransitionHelper = new TransitionHelper();
private final Uri mForeverId;
+ private final SpTexts mSpTexts;
private String mTag = TAG + "/" + Integer.toHexString(System.identityHashCode(this));
@@ -96,7 +97,7 @@ public class ZenModePanel extends LinearLayout {
private View mZenIntroduction;
private TextView mZenIntroductionMessage;
private View mZenIntroductionConfirm;
- private View mZenIntroductionCustomize;
+ private TextView mZenIntroductionCustomize;
private LinearLayout mZenConditions;
private TextView mZenAlarmWarning;
@@ -125,6 +126,7 @@ public class ZenModePanel extends LinearLayout {
mInflater = LayoutInflater.from(mContext.getApplicationContext());
mIconPulser = new IconPulser(mContext);
mForeverId = Condition.newId(mContext).appendPath("forever").build();
+ mSpTexts = new SpTexts(mContext);
if (DEBUG) Log.d(mTag, "new ZenModePanel");
}
@@ -151,15 +153,19 @@ public class ZenModePanel extends LinearLayout {
mZenButtons = (SegmentedButtons) findViewById(R.id.zen_buttons);
mZenButtons.addButton(R.string.interruption_level_none_twoline,
+ R.string.interruption_level_none,
Global.ZEN_MODE_NO_INTERRUPTIONS);
mZenButtons.addButton(R.string.interruption_level_alarms_twoline,
+ R.string.interruption_level_alarms,
Global.ZEN_MODE_ALARMS);
mZenButtons.addButton(R.string.interruption_level_priority_twoline,
+ R.string.interruption_level_priority,
Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
mZenButtons.setCallback(mZenButtonsCallback);
mZenIntroduction = findViewById(R.id.zen_introduction);
mZenIntroductionMessage = (TextView) findViewById(R.id.zen_introduction_message);
+ mSpTexts.add(mZenIntroductionMessage);
mZenIntroductionConfirm = findViewById(R.id.zen_introduction_confirm);
mZenIntroductionConfirm.setOnClickListener(new OnClickListener() {
@Override
@@ -167,7 +173,7 @@ public class ZenModePanel extends LinearLayout {
confirmZenIntroduction();
}
});
- mZenIntroductionCustomize = findViewById(R.id.zen_introduction_customize);
+ mZenIntroductionCustomize = (TextView) findViewById(R.id.zen_introduction_customize);
mZenIntroductionCustomize.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@@ -177,6 +183,7 @@ public class ZenModePanel extends LinearLayout {
}
}
});
+ mSpTexts.add(mZenIntroductionCustomize);
mZenConditions = (LinearLayout) findViewById(R.id.zen_conditions);
mZenAlarmWarning = (TextView) findViewById(R.id.zen_alarm_warning);
@@ -658,9 +665,11 @@ public class ZenModePanel extends LinearLayout {
}
if (tag.line1 == null) {
tag.line1 = (TextView) row.findViewById(android.R.id.text1);
+ mSpTexts.add(tag.line1);
}
if (tag.line2 == null) {
tag.line2 = (TextView) row.findViewById(android.R.id.text2);
+ mSpTexts.add(tag.line2);
}
final String line1 = !TextUtils.isEmpty(condition.line1) ? condition.line1
: condition.summary;