diff options
Diffstat (limited to 'packages/SystemUI/src')
50 files changed, 1154 insertions, 447 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java index 73fa2ed..98558b4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java @@ -108,15 +108,21 @@ public class KeyguardService extends Service { } @Override // Binder interface - public void onScreenTurnedOff(int reason) { + public void onStartedGoingToSleep(int reason) { checkPermission(); - mKeyguardViewMediator.onScreenTurnedOff(reason); + mKeyguardViewMediator.onStartedGoingToSleep(reason); } @Override // Binder interface - public void onScreenTurnedOn(IKeyguardShowCallback callback) { + public void onFinishedGoingToSleep(int reason) { checkPermission(); - mKeyguardViewMediator.onScreenTurnedOn(callback); + mKeyguardViewMediator.onFinishedGoingToSleep(reason); + } + + @Override // Binder interface + public void onStartedWakingUp(IKeyguardShowCallback callback) { + checkPermission(); + mKeyguardViewMediator.onStartedWakingUp(callback); } @Override // Binder interface diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 74962ec..0dcc0b9 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -33,6 +33,7 @@ import android.content.pm.UserInfo; import android.media.AudioManager; import android.media.SoundPool; import android.os.Bundle; +import android.os.DeadObjectException; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -188,11 +189,6 @@ public class KeyguardViewMediator extends SystemUI { private boolean mBootCompleted; private boolean mBootSendUserPresent; - // Whether the next call to playSounds() should be skipped. Defaults to - // true because the first lock (on boot) should be silent. - private boolean mSuppressNextLockSound = true; - - /** High level access to the power manager for WakeLocks */ private PowerManager mPM; @@ -255,7 +251,7 @@ public class KeyguardViewMediator extends SystemUI { private KeyguardUpdateMonitor mUpdateMonitor; - private boolean mScreenOn; + private boolean mDeviceInteractive; // last known state of the cellular connection private String mPhoneState = TelephonyManager.EXTRA_STATE_IDLE; @@ -306,6 +302,18 @@ public class KeyguardViewMediator extends SystemUI { private final ArrayList<IKeyguardStateCallback> mKeyguardStateCallbacks = new ArrayList<>(); + /** + * When starting going to sleep, we figured out that we need to reset Keyguard state and this + * should be committed when finished going to sleep. + */ + private boolean mPendingReset; + + /** + * When starting goign to sleep, we figured out that we need to lock Keyguard and this should be + * committed when finished going to sleep. + */ + private boolean mPendingLock; + KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() { @Override @@ -341,7 +349,7 @@ public class KeyguardViewMediator extends SystemUI { public void onPhoneStateChanged(int phoneState) { synchronized (KeyguardViewMediator.this) { if (TelephonyManager.CALL_STATE_IDLE == phoneState // call ending - && !mScreenOn // screen off + && !mDeviceInteractive // screen off && mExternallyEnabled) { // not disabled by any app // note: this is a way to gracefully reenable the keyguard when the call @@ -374,14 +382,17 @@ public class KeyguardViewMediator extends SystemUI { + ",state=" + simState + ")"); } - try { - int size = mKeyguardStateCallbacks.size(); - boolean simPinSecure = mUpdateMonitor.isSimPinSecure(); - for (int i = 0; i < size; i++) { + int size = mKeyguardStateCallbacks.size(); + boolean simPinSecure = mUpdateMonitor.isSimPinSecure(); + for (int i = size - 1; i >= 0; i--) { + try { mKeyguardStateCallbacks.get(i).onSimSecureStateChanged(simPinSecure); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to call onSimSecureStateChanged", e); + if (e instanceof DeadObjectException) { + mKeyguardStateCallbacks.remove(i); + } } - } catch (RemoteException e) { - Slog.w(TAG, "Failed to call onSimSecureStateChanged", e); } switch (simState) { @@ -514,7 +525,7 @@ public class KeyguardViewMediator extends SystemUI { @Override public boolean isScreenOn() { - return mScreenOn; + return mDeviceInteractive; } }; @@ -544,13 +555,14 @@ public class KeyguardViewMediator extends SystemUI { // Assume keyguard is showing (unless it's disabled) until we know for sure... setShowingLocked(!shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled( KeyguardUpdateMonitor.getCurrentUser())); + updateInputRestrictedLocked(); mTrustManager.reportKeyguardShowingChanged(); mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(mContext, mViewMediatorCallback, mLockPatternUtils); final ContentResolver cr = mContext.getContentResolver(); - mScreenOn = mPM.isScreenOn(); + mDeviceInteractive = mPM.isInteractive(); mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0); String soundPath = Settings.Global.getString(cr, Settings.Global.LOCK_SOUND); @@ -613,23 +625,18 @@ public class KeyguardViewMediator extends SystemUI { * @param why either {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_USER} or * {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT}. */ - public void onScreenTurnedOff(int why) { + public void onStartedGoingToSleep(int why) { + if (DEBUG) Log.d(TAG, "onStartedGoingToSleep(" + why + ")"); synchronized (this) { - mScreenOn = false; - if (DEBUG) Log.d(TAG, "onScreenTurnedOff(" + why + ")"); - - resetKeyguardDonePendingLocked(); - mHideAnimationRun = false; + mDeviceInteractive = false; // Lock immediately based on setting if secure (user has a pin/pattern/password). // This also "locks" the device when not secure to provide easy access to the // camera while preventing unwanted input. int currentUser = KeyguardUpdateMonitor.getCurrentUser(); final boolean lockImmediately = - mLockPatternUtils.getPowerButtonInstantlyLocks(currentUser) - || !mLockPatternUtils.isSecure(currentUser); - - notifyScreenOffLocked(); + mLockPatternUtils.getPowerButtonInstantlyLocks(currentUser) + || !mLockPatternUtils.isSecure(currentUser); if (mExitSecureCallback != null) { if (DEBUG) Log.d(TAG, "pending exit secure callback cancelled"); @@ -643,12 +650,37 @@ public class KeyguardViewMediator extends SystemUI { hideLocked(); } } else if (mShowing) { - resetStateLocked(); + mPendingReset = true; } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT - || (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) { + || (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) { doKeyguardLaterLocked(); - } else { + } else if (!mLockPatternUtils.isLockScreenDisabled(currentUser)) { + mPendingLock = true; + } + + if (mPendingLock || mPendingReset) { + playSounds(true); + } + } + } + + public void onFinishedGoingToSleep(int why) { + if (DEBUG) Log.d(TAG, "onFinishedGoingToSleep(" + why + ")"); + synchronized (this) { + mDeviceInteractive = false; + + resetKeyguardDonePendingLocked(); + mHideAnimationRun = false; + + notifyScreenOffLocked(); + + if (mPendingReset) { + resetStateLocked(); + mPendingReset = false; + } + if (mPendingLock) { doKeyguardLocked(null); + mPendingLock = false; } } KeyguardUpdateMonitor.getInstance(mContext).dispatchScreenTurnedOff(why); @@ -686,7 +718,6 @@ public class KeyguardViewMediator extends SystemUI { if (timeout <= 0) { // Lock now - mSuppressNextLockSound = true; doKeyguardLocked(null); } else { // Lock in the future @@ -706,13 +737,15 @@ public class KeyguardViewMediator extends SystemUI { } /** - * Let's us know the screen was turned on. + * Let's us know when the device is waking up. */ - public void onScreenTurnedOn(IKeyguardShowCallback callback) { + public void onStartedWakingUp(IKeyguardShowCallback callback) { + + // TODO: Rename all screen off/on references to interactive/sleeping synchronized (this) { - mScreenOn = true; + mDeviceInteractive = true; cancelDoKeyguardLaterLocked(); - if (DEBUG) Log.d(TAG, "onScreenTurnedOn, seq = " + mDelayedShowingSequence); + if (DEBUG) Log.d(TAG, "onStartedWakingUp, seq = " + mDelayedShowingSequence); if (callback != null) { notifyScreenOnLocked(callback); } @@ -737,7 +770,8 @@ public class KeyguardViewMediator extends SystemUI { */ public void onDreamingStarted() { synchronized (this) { - if (mScreenOn && mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) { + if (mDeviceInteractive + && mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())) { doKeyguardLaterLocked(); } } @@ -748,7 +782,7 @@ public class KeyguardViewMediator extends SystemUI { */ public void onDreamingStopped() { synchronized (this) { - if (mScreenOn) { + if (mDeviceInteractive) { cancelDoKeyguardLaterLocked(); } } @@ -925,13 +959,16 @@ public class KeyguardViewMediator extends SystemUI { boolean inputRestricted = isInputRestricted(); if (mInputRestricted != inputRestricted) { mInputRestricted = inputRestricted; - try { - int size = mKeyguardStateCallbacks.size(); - for (int i = 0; i < size; i++) { + int size = mKeyguardStateCallbacks.size(); + for (int i = size - 1; i >= 0; i--) { + try { mKeyguardStateCallbacks.get(i).onInputRestrictedStateChanged(inputRestricted); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to call onDeviceProvisioned", e); + if (e instanceof DeadObjectException) { + mKeyguardStateCallbacks.remove(i); + } } - } catch (RemoteException e) { - Slog.w(TAG, "Failed to call onDeviceProvisioned", e); } } } @@ -1100,8 +1137,6 @@ public class KeyguardViewMediator extends SystemUI { + sequence + ", mDelayedShowingSequence = " + mDelayedShowingSequence); synchronized (KeyguardViewMediator.this) { if (mDelayedShowingSequence == sequence) { - // Don't play lockscreen SFX if the screen went off due to timeout. - mSuppressNextLockSound = true; doKeyguardLocked(null); } } @@ -1252,13 +1287,6 @@ public class KeyguardViewMediator extends SystemUI { } private void playSounds(boolean locked) { - // User feedback for keyguard. - - if (mSuppressNextLockSound) { - mSuppressNextLockSound = false; - return; - } - playSound(locked ? mLockSoundId : mUnlockSoundId); } @@ -1283,9 +1311,6 @@ public class KeyguardViewMediator extends SystemUI { } private void playTrustedSound() { - if (mSuppressNextLockSound) { - return; - } playSound(mTrustedSoundId); } @@ -1318,9 +1343,6 @@ public class KeyguardViewMediator extends SystemUI { adjustStatusBarLocked(); userActivity(); - // Do this at the end to not slow down display of the keyguard. - playSounds(true); - mShowKeyguardWakeLock.release(); } mKeyguardDisplayManager.show(); @@ -1530,13 +1552,16 @@ public class KeyguardViewMediator extends SystemUI { private void setShowingLocked(boolean showing) { if (showing != mShowing) { mShowing = showing; - try { - int size = mKeyguardStateCallbacks.size(); - for (int i = 0; i < size; i++) { + int size = mKeyguardStateCallbacks.size(); + for (int i = size - 1; i >= 0; i--) { + try { mKeyguardStateCallbacks.get(i).onShowingStateChanged(showing); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to call onShowingStateChanged", e); + if (e instanceof DeadObjectException) { + mKeyguardStateCallbacks.remove(i); + } } - } catch (RemoteException e) { - Slog.w(TAG, "Failed to call onShowingStateChanged", e); } updateInputRestrictedLocked(); mTrustManager.reportKeyguardShowingChanged(); @@ -1551,7 +1576,7 @@ public class KeyguardViewMediator extends SystemUI { callback.onShowingStateChanged(mShowing); callback.onInputRestrictedStateChanged(mInputRestricted); } catch (RemoteException e) { - Slog.w(TAG, "Failed to call onShowingStateChanged or onSimSecureStateChanged", e); + Slog.w(TAG, "Failed to call onShowingStateChanged or onSimSecureStateChanged or onInputRestrictedStateChanged", e); } } } diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java index af1f795..a12a3f1 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java @@ -376,7 +376,8 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI { filter.addAction(ACTION_START_SAVER); filter.addAction(ACTION_STOP_SAVER); filter.addAction(ACTION_DISMISSED_WARNING); - mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, null, mHandler); + mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, + android.Manifest.permission.STATUS_BAR_SERVICE, mHandler); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java index dcf0438..a9e8b38 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -162,10 +162,9 @@ public class CellularTile extends QSTile<QSTile.SignalState> { } @Override - public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, - int darkStatusIcon, int statusType, int qsType, boolean activityIn, - boolean activityOut, String typeContentDescription, String description, - boolean isWide, int subId) { + public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, + int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, + String description, boolean isWide, int subId) { if (qsIcon == null) { // Not data sim, don't display. return; 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/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java index c7f8919..18c213d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java @@ -29,8 +29,6 @@ public class Constants { public static final boolean EnableTransitionThumbnailDebugMode = false; // Enables the filtering of tasks according to their grouping public static final boolean EnableTaskFiltering = false; - // Enables app-info pane on long-pressing the icon - public static final boolean EnableDevAppInfoOnLongPress = true; // Enables dismiss-all public static final boolean EnableDismissAll = false; // Enables debug mode diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java index c702673..7d2b5c87 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java @@ -32,13 +32,16 @@ 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; +import android.util.MutableBoolean; 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; @@ -57,7 +60,6 @@ import com.android.systemui.recents.views.TaskViewTransform; import com.android.systemui.statusbar.phone.PhoneStatusBar; import java.util.ArrayList; -import java.util.concurrent.atomic.AtomicBoolean; /** * Annotation for a method that is only called from the primary user's SystemUI process and will be @@ -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() { } @@ -360,9 +366,17 @@ 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) + ActivityManager.RunningTaskInfo topTask = mSystemServicesProxy.getTopMostTask(); + MutableBoolean topTaskHome = new MutableBoolean(true); RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); sInstanceLoadPlan = loader.createLoadPlan(mContext); - sInstanceLoadPlan.preloadRawTasks(true); + if (topTask != null && !mSystemServicesProxy.isRecentsTopMost(topTask, topTaskHome)) { + sInstanceLoadPlan.preloadRawTasks(topTaskHome.value); + loader.preloadTasks(sInstanceLoadPlan, topTaskHome.value); + TaskStack top = sInstanceLoadPlan.getAllTaskStacks().get(0); + preCacheThumbnailTransitionBitmapAsync(topTask, top, mDummyStackView, + topTaskHome.value); + } } @Override @@ -508,12 +522,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 */ @@ -546,7 +562,7 @@ public class Recents extends SystemUI // If Recents is the front most activity, then we should just communicate with it directly // to launch the first task or dismiss itself ActivityManager.RunningTaskInfo topTask = mSystemServicesProxy.getTopMostTask(); - AtomicBoolean isTopTaskHome = new AtomicBoolean(true); + MutableBoolean isTopTaskHome = new MutableBoolean(true); if (topTask != null && mSystemServicesProxy.isRecentsTopMost(topTask, isTopTaskHome)) { // Notify recents to toggle itself Intent intent = createLocalBroadcastIntent(mContext, ACTION_TOGGLE_RECENTS_ACTIVITY); @@ -555,7 +571,7 @@ public class Recents extends SystemUI return; } else { // Otherwise, start the recents activity - startRecentsActivity(topTask, isTopTaskHome.get()); + startRecentsActivity(topTask, isTopTaskHome.value); } } @@ -563,9 +579,9 @@ public class Recents extends SystemUI void startRecentsActivity() { // Check if the top task is in the home stack, and start the recents activity ActivityManager.RunningTaskInfo topTask = mSystemServicesProxy.getTopMostTask(); - AtomicBoolean isTopTaskHome = new AtomicBoolean(true); + MutableBoolean isTopTaskHome = new MutableBoolean(true); if (topTask == null || !mSystemServicesProxy.isRecentsTopMost(topTask, isTopTaskHome)) { - startRecentsActivity(topTask, isTopTaskHome.get()); + startRecentsActivity(topTask, isTopTaskHome.value); } } @@ -602,30 +618,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); } @@ -633,6 +646,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) { @@ -654,6 +733,7 @@ public class Recents extends SystemUI if (task == null) { // If no task is specified or we can not find the task just use the front most one task = tasks.get(tasks.size() - 1); + runningTaskOut.copyFrom(task); } // Get the transform for the running task @@ -688,7 +768,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); @@ -700,12 +782,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/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index ca0f357..272d39a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -54,6 +54,7 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; import android.util.Log; +import android.util.MutableBoolean; import android.util.Pair; import android.util.SparseArray; import android.view.Display; @@ -67,12 +68,9 @@ import com.android.systemui.recents.Recents; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Random; -import java.util.concurrent.atomic.AtomicBoolean; /** * Acts as a shim around the real system services that we need to access data from, and provides @@ -192,7 +190,7 @@ public class SystemServicesProxy { // Break early if we can't get a valid set of tasks if (tasks == null) { - return new ArrayList<ActivityManager.RecentTaskInfo>(); + return new ArrayList<>(); } boolean isFirstValidTask = true; @@ -235,7 +233,7 @@ public class SystemServicesProxy { /** Returns whether the recents is currently running */ public boolean isRecentsTopMost(ActivityManager.RunningTaskInfo topTask, - AtomicBoolean isHomeTopMost) { + MutableBoolean isHomeTopMost) { if (topTask != null) { ComponentName topActivity = topTask.topActivity; @@ -243,13 +241,13 @@ public class SystemServicesProxy { if (topActivity.getPackageName().equals(Recents.sRecentsPackage) && topActivity.getClassName().equals(Recents.sRecentsActivity)) { if (isHomeTopMost != null) { - isHomeTopMost.set(false); + isHomeTopMost.value = false; } return true; } if (isHomeTopMost != null) { - isHomeTopMost.set(isInHomeStack(topTask.id)); + isHomeTopMost.value = isInHomeStack(topTask.id); } } return false; diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java index 40cd211..f40c58d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java @@ -104,13 +104,9 @@ public class RecentsTaskLoadPlan { if (mRawTasks == null) { preloadRawTasks(isTopTaskHome); } - int firstStackId = -1; int taskCount = mRawTasks.size(); for (int i = 0; i < taskCount; i++) { ActivityManager.RecentTaskInfo t = mRawTasks.get(i); - if (firstStackId < 0) { - firstStackId = t.stackId; - } // Compose the task key Task.TaskKey taskKey = new Task.TaskKey(t.persistentId, t.stackId, t.baseIntent, @@ -158,17 +154,17 @@ public class RecentsTaskLoadPlan { if (!mConfig.multiStackEnabled || Constants.DebugFlags.App.EnableMultiStackToSingleStack) { - firstStackId = 0; + int firstStackId = 0; ArrayList<Task> stackTasks = stacksTasks.get(firstStackId); if (stackTasks == null) { - stackTasks = new ArrayList<Task>(); + stackTasks = new ArrayList<>(); stacksTasks.put(firstStackId, stackTasks); } stackTasks.add(task); } else { ArrayList<Task> stackTasks = stacksTasks.get(t.stackId); if (stackTasks == null) { - stackTasks = new ArrayList<Task>(); + stackTasks = new ArrayList<>(); stacksTasks.put(t.stackId, stackTasks); } stackTasks.add(task); 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 b3e6221..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); } } @@ -550,7 +601,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV if (tv == null) { launchRunnable.run(); } else { - if (!task.group.isFrontMostTask(task)) { + if (task.group != null && !task.group.isFrontMostTask(task)) { // For affiliated tasks that are behind other tasks, we must animate the front cards // out of view before starting the task transition stackView.startLaunchTaskAnimation(tv, launchRunnable, lockToTask); 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 3a97a41..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 @@ -880,8 +882,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } // Start the focus animation when alt-tabbing - if (mConfig.launchedWithAltTab && !mConfig.launchedHasConfigurationChanged) { - TaskView tv = getChildViewForTask(mStack.getTasks().get(mFocusedTaskIndex)); + ArrayList<Task> tasks = mStack.getTasks(); + if (mConfig.launchedWithAltTab && !mConfig.launchedHasConfigurationChanged && + 0 <= mFocusedTaskIndex && mFocusedTaskIndex < tasks.size()) { + TaskView tv = getChildViewForTask(tasks.get(mFocusedTaskIndex)); if (tv != null) { tv.setFocusedTask(true); } @@ -1029,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 682775b..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,17 +675,17 @@ 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); } mActionButtonView.setOnClickListener(this); - if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) { - if (mConfig.developerOptionsEnabled) { - mHeaderView.mApplicationIcon.setOnLongClickListener(this); - } - } + mHeaderView.mApplicationIcon.setOnLongClickListener(this); } mTaskDataLoaded = true; } @@ -701,9 +704,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, mHeaderView.mMoveTaskButton.setOnClickListener(null); } mActionButtonView.setOnClickListener(null); - if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) { - mHeaderView.mApplicationIcon.setOnLongClickListener(null); - } + mHeaderView.mApplicationIcon.setOnLongClickListener(null); } mTaskDataLoaded = false; } @@ -724,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..062ded2 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -80,6 +80,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 +174,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,7 +194,6 @@ 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); } @@ -263,7 +266,6 @@ public class TaskViewHeader extends FrameLayout { .setStartDelay(0) .setInterpolator(mConfig.fastOutSlowInInterpolator) .setDuration(mConfig.taskViewExitToAppDuration) - .withLayer() .start(); } } @@ -278,7 +280,6 @@ public class TaskViewHeader extends FrameLayout { .setStartDelay(0) .setInterpolator(mConfig.fastOutLinearInInterpolator) .setDuration(mConfig.taskViewEnterFromAppDuration) - .withLayer() .start(); } } @@ -305,6 +306,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/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java index 7e32c3a..9e3cf37 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java @@ -60,6 +60,7 @@ import android.widget.ImageView; import com.android.systemui.R; import java.io.File; +import java.io.FileOutputStream; import java.io.OutputStream; import java.text.DateFormat; import java.text.SimpleDateFormat; @@ -179,7 +180,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi .setColor(r.getColor(com.android.internal.R.color.system_notification_accent_color)); mNotificationStyle = new Notification.BigPictureStyle() - .bigPicture(picture); + .bigPicture(picture.createAshmemBitmap()); mNotificationBuilder.setStyle(mNotificationStyle); // For "public" situations we want to show all the same info but @@ -202,7 +203,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi // On the tablet, the large icon makes the notification appear as if it is clickable (and // on small devices, the large icon is not shown) so defer showing the large icon until // we compose the final post-save notification below. - mNotificationBuilder.setLargeIcon(icon); + mNotificationBuilder.setLargeIcon(icon.createAshmemBitmap()); // But we still don't set it for the expanded view, allowing the smallIcon to show here. mNotificationStyle.bigLargeIcon((Bitmap) null); } @@ -232,6 +233,12 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi // for DATE_TAKEN long dateSeconds = mImageTime / 1000; + // Save + OutputStream out = new FileOutputStream(mImageFilePath); + image.compress(Bitmap.CompressFormat.PNG, 100, out); + out.flush(); + out.close(); + // Save the screenshot to the MediaStore ContentValues values = new ContentValues(); ContentResolver resolver = context.getContentResolver(); @@ -244,8 +251,10 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png"); values.put(MediaStore.Images.ImageColumns.WIDTH, mImageWidth); values.put(MediaStore.Images.ImageColumns.HEIGHT, mImageHeight); + values.put(MediaStore.Images.ImageColumns.SIZE, new File(mImageFilePath).length()); Uri uri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); + // Create a share intent String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime)); String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate); Intent sharingIntent = new Intent(Intent.ACTION_SEND); @@ -253,16 +262,6 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi sharingIntent.putExtra(Intent.EXTRA_STREAM, uri); sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject); - OutputStream out = resolver.openOutputStream(uri); - image.compress(Bitmap.CompressFormat.PNG, 100, out); - out.flush(); - out.close(); - - // Update file size in the database - values.clear(); - values.put(MediaStore.Images.ImageColumns.SIZE, new File(mImageFilePath).length()); - resolver.update(uri, values, null, null); - // Create a share action for the notification final PendingIntent callback = PendingIntent.getBroadcast(context, 0, new Intent(context, GlobalScreenshot.TargetChosenReceiver.class) diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java index 9fbcd7f..d6a16fa 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java +++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java @@ -40,7 +40,7 @@ public class BrightnessController implements ToggleSlider.Listener { * {@link android.provider.Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ} uses the range [-1, 1]. * Using this factor, it is converted to [0, BRIGHTNESS_ADJ_RESOLUTION] for the SeekBar. */ - private static final float BRIGHTNESS_ADJ_RESOLUTION = 100; + private static final float BRIGHTNESS_ADJ_RESOLUTION = 2048; private final int mMinimumBacklight; private final int mMaximumBacklight; diff --git a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java index 35b574b..8abfe03 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java +++ b/packages/SystemUI/src/com/android/systemui/settings/ToggleSlider.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.util.AttributeSet; +import android.view.MotionEvent; import android.view.View; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; @@ -123,6 +124,16 @@ public class ToggleSlider extends RelativeLayout { } } + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (mMirror != null) { + MotionEvent copy = ev.copy(); + mMirror.dispatchTouchEvent(copy); + copy.recycle(); + } + return super.dispatchTouchEvent(ev); + } + private final OnCheckedChangeListener mCheckListener = new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton toggle, boolean checked) { @@ -146,10 +157,6 @@ public class ToggleSlider extends RelativeLayout { mListener.onChanged( ToggleSlider.this, mTracking, mToggle.isChecked(), progress); } - - if (mMirror != null) { - mMirror.setValue(progress); - } } @Override @@ -163,10 +170,6 @@ public class ToggleSlider extends RelativeLayout { mToggle.setChecked(false); - if (mMirror != null) { - mMirror.mSlider.setPressed(true); - } - if (mMirrorController != null) { mMirrorController.showMirror(); mMirrorController.setLocation((View) getParent()); @@ -182,10 +185,6 @@ public class ToggleSlider extends RelativeLayout { ToggleSlider.this, mTracking, mToggle.isChecked(), mSlider.getProgress()); } - if (mMirror != null) { - mMirror.mSlider.setPressed(false); - } - if (mMirrorController != null) { mMirrorController.hideMirror(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index f23efe5..6fb4b48 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -1030,9 +1030,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 diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java index 9ccff72..374d970 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java @@ -23,11 +23,14 @@ import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; +import android.graphics.CanvasProperty; import android.graphics.Color; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.util.AttributeSet; +import android.view.DisplayListCanvas; +import android.view.RenderNodeAnimator; import android.view.View; import android.view.ViewAnimationUtils; import android.view.animation.AnimationUtils; @@ -35,6 +38,7 @@ import android.view.animation.Interpolator; import android.widget.ImageView; import com.android.systemui.R; import com.android.systemui.statusbar.phone.KeyguardAffordanceHelper; +import com.android.systemui.statusbar.phone.PhoneStatusBar; /** * An ImageView which does not have overlapping renderings commands and therefore does not need a @@ -77,6 +81,14 @@ public class KeyguardAffordanceView extends ImageView { private float mMaxCircleSize; private Animator mPreviewClipper; private float mRestingAlpha = KeyguardAffordanceHelper.SWIPE_RESTING_ALPHA_AMOUNT; + private boolean mSupportHardware; + private boolean mFinishing; + + private CanvasProperty<Float> mHwCircleRadius; + private CanvasProperty<Float> mHwCenterX; + private CanvasProperty<Float> mHwCenterY; + private CanvasProperty<Paint> mHwCirclePaint; + private AnimatorListenerAdapter mClipEndListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -155,6 +167,7 @@ public class KeyguardAffordanceView extends ImageView { @Override protected void onDraw(Canvas canvas) { + mSupportHardware = canvas.isHardwareAccelerated(); drawBackgroundCircle(canvas); drawArrow(canvas); canvas.save(); @@ -196,8 +209,14 @@ public class KeyguardAffordanceView extends ImageView { private void drawBackgroundCircle(Canvas canvas) { if (mCircleRadius > 0) { - updateCircleColor(); - canvas.drawCircle(mCenterX, mCenterY, mCircleRadius, mCirclePaint); + if (mFinishing && mSupportHardware) { + DisplayListCanvas displayListCanvas = (DisplayListCanvas) canvas; + displayListCanvas.drawCircle(mHwCenterX, mHwCenterY, mHwCircleRadius, + mHwCirclePaint); + } else { + updateCircleColor(); + canvas.drawCircle(mCenterX, mCenterY, mCircleRadius, mCirclePaint); + } } } @@ -218,15 +237,23 @@ public class KeyguardAffordanceView extends ImageView { public void finishAnimation(float velocity, final Runnable mAnimationEndRunnable) { cancelAnimator(mCircleAnimator); cancelAnimator(mPreviewClipper); + mFinishing = true; mCircleStartRadius = mCircleRadius; float maxCircleSize = getMaxCircleSize(); - ValueAnimator animatorToRadius = getAnimatorToRadius(maxCircleSize); + Animator animatorToRadius; + if (mSupportHardware) { + initHwProperties(); + animatorToRadius = getRtAnimatorToRadius(maxCircleSize); + } else { + animatorToRadius = getAnimatorToRadius(maxCircleSize); + } mFlingAnimationUtils.applyDismissing(animatorToRadius, mCircleRadius, maxCircleSize, velocity, maxCircleSize); animatorToRadius.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mAnimationEndRunnable.run(); + mFinishing = false; } }); animatorToRadius.start(); @@ -240,9 +267,34 @@ public class KeyguardAffordanceView extends ImageView { velocity, maxCircleSize); mPreviewClipper.addListener(mClipEndListener); mPreviewClipper.start(); + if (mSupportHardware) { + startRtCircleFadeOut(animatorToRadius.getDuration()); + } } } + private void startRtCircleFadeOut(long duration) { + RenderNodeAnimator animator = new RenderNodeAnimator(mHwCirclePaint, + RenderNodeAnimator.PAINT_ALPHA, 0); + animator.setDuration(duration); + animator.setInterpolator(PhoneStatusBar.ALPHA_OUT); + animator.setTarget(this); + animator.start(); + } + + private Animator getRtAnimatorToRadius(float circleRadius) { + RenderNodeAnimator animator = new RenderNodeAnimator(mHwCircleRadius, circleRadius); + animator.setTarget(this); + return animator; + } + + private void initHwProperties() { + mHwCenterX = CanvasProperty.createFloat(mCenterX); + mHwCenterY = CanvasProperty.createFloat(mCenterY); + mHwCirclePaint = CanvasProperty.createPaint(mCirclePaint); + mHwCircleRadius = CanvasProperty.createFloat(mCircleRadius); + } + private float getMaxCircleSize() { getLocationInWindow(mTempPoint); float rootWidth = getRootView().getWidth(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java index 991bde5..02e196e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -18,10 +18,13 @@ 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.AttributeSet; import android.util.Log; @@ -33,6 +36,7 @@ import android.widget.ImageView; import android.widget.LinearLayout; import com.android.systemui.R; +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; @@ -49,6 +53,11 @@ public class SignalClusterView static final String TAG = "SignalClusterView"; static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private static final String SLOT_AIRPLANE = "airplane"; + private static final String SLOT_MOBILE = "mobile"; + private static final String SLOT_WIFI = "wifi"; + private static final String SLOT_ETHERNET = "ethernet"; + NetworkControllerImpl mNC; SecurityController mSC; @@ -81,6 +90,11 @@ public class SignalClusterView private int mEndPadding; private int mEndPaddingNothingVisible; + private boolean mBlockAirplane; + private boolean mBlockMobile; + private boolean mBlockWifi; + private boolean mBlockEthernet; + public SignalClusterView(Context context) { this(context, null); } @@ -91,6 +105,14 @@ 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); } public void setNetworkController(NetworkControllerImpl nc) { @@ -141,6 +163,9 @@ public class SignalClusterView apply(); applyIconTint(); + getContext().getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(StatusBarIconController.ICON_BLACKLIST), false, + mBlacklistObserver); } @Override @@ -153,6 +178,7 @@ public class SignalClusterView mAirplane = null; mMobileSignalGroup.removeAllViews(); mMobileSignalGroup = null; + getContext().getContentResolver().unregisterContentObserver(mBlacklistObserver); super.onDetachedFromWindow(); } @@ -172,7 +198,7 @@ public class SignalClusterView @Override public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon, boolean activityIn, boolean activityOut, String description) { - mWifiVisible = statusIcon.visible; + mWifiVisible = statusIcon.visible && !mBlockWifi; mWifiStrengthId = statusIcon.icon; mWifiDescription = statusIcon.contentDescription; @@ -180,13 +206,12 @@ public class SignalClusterView } @Override - public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int darkStatusIcon, - int statusType, int qsType, boolean activityIn, boolean activityOut, - String typeContentDescription, String description, boolean isWide, int subId) { + public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, + int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, + String description, boolean isWide, int subId) { PhoneState state = getOrInflateState(subId); - state.mMobileVisible = statusIcon.visible; + state.mMobileVisible = statusIcon.visible && !mBlockMobile; state.mMobileStrengthId = statusIcon.icon; - state.mMobileDarkStrengthId = darkStatusIcon; state.mMobileTypeId = statusType; state.mMobileDescription = statusIcon.contentDescription; state.mMobileTypeDescription = typeContentDescription; @@ -197,7 +222,7 @@ public class SignalClusterView @Override public void setEthernetIndicators(IconState state) { - mEthernetVisible = state.visible; + mEthernetVisible = state.visible && !mBlockEthernet; mEthernetIconId = state.icon; mEthernetDescription = state.contentDescription; @@ -206,7 +231,7 @@ public class SignalClusterView @Override public void setNoSims(boolean show) { - mNoSimsVisible = show; + mNoSimsVisible = show && !mBlockMobile; } @Override @@ -245,7 +270,7 @@ public class SignalClusterView @Override public void setIsAirplaneMode(IconState icon) { - mIsAirplaneMode = icon.visible; + mIsAirplaneMode = icon.visible && !mBlockAirplane; mAirplaneIconId = icon.icon; mAirplaneContentDescription = icon.contentDescription; @@ -426,7 +451,7 @@ public class SignalClusterView private class PhoneState { private final int mSubId; private boolean mMobileVisible = false; - private int mMobileStrengthId = 0, mMobileDarkStrengthId = 0, mMobileTypeId = 0; + private int mMobileStrengthId = 0, mMobileTypeId = 0; private boolean mIsMobileTypeIconWide; private String mMobileDescription, mMobileTypeDescription; @@ -483,9 +508,8 @@ public class SignalClusterView mMobileDark.setPaddingRelative(mIsMobileTypeIconWide ? mWideTypeIconStartPadding : 0, 0, 0, 0); - if (DEBUG) Log.d(TAG, String.format("mobile: %s sig=%d dark=%d typ=%d", - (mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, - mMobileDarkStrengthId, mMobileTypeId)); + if (DEBUG) Log.d(TAG, String.format("mobile: %s sig=%d typ=%d", + (mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, mMobileTypeId)); mMobileType.setVisibility(mMobileTypeId != 0 ? View.VISIBLE : View.GONE); @@ -504,5 +528,14 @@ 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/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 3294e15..baac8ac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -18,7 +18,6 @@ package com.android.systemui.statusbar; import android.app.Notification; import android.content.Context; -import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Paint; @@ -49,10 +48,17 @@ public class StatusBarIconView extends AnimatedImageView { private int mNumberY; private String mNumberText; private Notification mNotification; + private final boolean mBlocked; public StatusBarIconView(Context context, String slot, Notification notification) { + this(context, slot, notification, false); + } + + public StatusBarIconView(Context context, String slot, Notification notification, + boolean blocked) { super(context); final Resources res = context.getResources(); + mBlocked = blocked; mSlot = slot; mNumberPain = new Paint(); mNumberPain.setTextAlign(Paint.Align.CENTER); @@ -80,6 +86,7 @@ public class StatusBarIconView extends AnimatedImageView { public StatusBarIconView(Context context, AttributeSet attrs) { super(context, attrs); + mBlocked = false; final Resources res = context.getResources(); final int outerBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_size); final int imageBounds = res.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size); @@ -148,7 +155,7 @@ public class StatusBarIconView extends AnimatedImageView { invalidate(); } if (!visibilityEquals) { - setVisibility(icon.visible ? VISIBLE : GONE); + setVisibility(icon.visible && !mBlocked ? VISIBLE : GONE); } return true; } @@ -281,4 +288,8 @@ public class StatusBarIconView extends AnimatedImageView { return "StatusBarIconView(slot=" + mSlot + " icon=" + mIcon + " notification=" + mNotification + ")"; } + + public String getSlot() { + return mSlot; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java index ee5eb38..9ef320b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java @@ -24,6 +24,11 @@ import android.content.Intent; * Keyguard. */ public interface ActivityStarter { - public void startActivity(Intent intent, boolean dismissShade); + void startActivity(Intent intent, boolean dismissShade); + void startActivity(Intent intent, boolean dismissShade, Callback callback); void preventNextAnimation(); + + interface Callback { + void onActivityStarted(int resultCode); + } } 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 8bffdc9..64735ee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java @@ -160,7 +160,7 @@ public class KeyguardAffordanceHelper { } else { mTouchSlopExeeded = false; } - mCallback.onSwipingStarted(targetView == mLeftIcon); + mCallback.onSwipingStarted(targetView == mRightIcon); mSwipingInProgress = true; mTargetedView = targetView; mInitialTouchX = x; @@ -550,7 +550,7 @@ public class KeyguardAffordanceHelper { float getMaxTranslationDistance(); - void onSwipingStarted(boolean isRightwardMotion); + void onSwipingStarted(boolean rightIcon); void onSwipingAborted(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index adee5a8..3258a9f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -16,12 +16,17 @@ package com.android.systemui.statusbar.phone; +import android.app.ActivityManager; import android.app.ActivityManagerNative; +import android.app.Application; import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; @@ -29,9 +34,13 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.InsetDrawable; import android.os.AsyncTask; import android.os.Bundle; +import android.os.IBinder; +import android.os.Message; +import android.os.Messenger; import android.os.RemoteException; import android.os.UserHandle; import android.provider.MediaStore; +import android.service.media.CameraPrewarmService; import android.telecom.TelecomManager; import android.util.AttributeSet; import android.util.Log; @@ -100,7 +109,23 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private PhoneStatusBar mPhoneStatusBar; private final Interpolator mLinearOutSlowInInterpolator; - private boolean mPrewarmSent; + private boolean mPrewarmBound; + private Messenger mPrewarmMessenger; + private final ServiceConnection mPrewarmConnection = new ServiceConnection() { + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + mPrewarmMessenger = new Messenger(service); + mPrewarmBound = true; + } + + @Override + public void onServiceDisconnected(ComponentName name) { + mPrewarmBound = false; + mPrewarmMessenger = null; + } + }; + private boolean mLeftIsVoiceAssist; private AssistManager mAssistManager; @@ -343,37 +368,44 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mLockPatternUtils.requireCredentialEntry(KeyguardUpdateMonitor.getCurrentUser()); } - public void prewarmCamera() { + public void bindCameraPrewarmService() { Intent intent = getCameraIntent(); - String targetPackage = PreviewInflater.getTargetPackage(mContext, intent, + ActivityInfo targetInfo = PreviewInflater.getTargetActivityInfo(mContext, intent, KeyguardUpdateMonitor.getCurrentUser()); - if (targetPackage != null) { - Intent prewarm = new Intent(MediaStore.ACTION_STILL_IMAGE_CAMERA_PREWARM); - prewarm.setPackage(targetPackage); - mPrewarmSent = true; - mContext.sendBroadcast(prewarm); + if (targetInfo != null) { + String clazz = targetInfo.metaData.getString( + MediaStore.META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE); + if (clazz != null) { + Intent serviceIntent = new Intent(); + serviceIntent.setClassName(targetInfo.packageName, clazz); + serviceIntent.setAction(CameraPrewarmService.ACTION_PREWARM); + try { + getContext().bindServiceAsUser(serviceIntent, mPrewarmConnection, + Context.BIND_AUTO_CREATE, new UserHandle(UserHandle.USER_CURRENT)); + } catch (SecurityException e) { + Log.w(TAG, "Unable to bind to prewarm service package=" + targetInfo.packageName + + " class=" + clazz, e); + } + } } } - public void maybeCooldownCamera() { - if (!mPrewarmSent) { - return; - } - mPrewarmSent = false; - Intent intent = getCameraIntent(); - String targetPackage = PreviewInflater.getTargetPackage(mContext, intent, - KeyguardUpdateMonitor.getCurrentUser()); - if (targetPackage != null) { - Intent prewarm = new Intent(MediaStore.ACTION_STILL_IMAGE_CAMERA_COOLDOWN); - prewarm.setPackage(targetPackage); - mContext.sendBroadcast(prewarm); + public void unbindCameraPrewarmService(boolean launched) { + if (mPrewarmBound) { + if (launched) { + try { + mPrewarmMessenger.send(Message.obtain(null /* handler */, + CameraPrewarmService.MSG_CAMERA_FIRED)); + } catch (RemoteException e) { + Log.w(TAG, "Error sending camera fired message", e); + } + } + mContext.unbindService(mPrewarmConnection); + mPrewarmBound = false; } } public void launchCamera() { - - // Reset prewarm state. - mPrewarmSent = false; final Intent intent = getCameraIntent(); boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity( mContext, intent, KeyguardUpdateMonitor.getCurrentUser()); @@ -381,18 +413,47 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL AsyncTask.execute(new Runnable() { @Override public void run() { - mContext.startActivityAsUser(intent, UserHandle.CURRENT); + int result = ActivityManager.START_CANCELED; + try { + result = ActivityManagerNative.getDefault().startActivityAsUser( + null, getContext().getBasePackageName(), + intent, + intent.resolveTypeIfNeeded(getContext().getContentResolver()), + null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null, + UserHandle.CURRENT.getIdentifier()); + } catch (RemoteException e) { + Log.w(TAG, "Unable to start camera activity", e); + } mActivityStarter.preventNextAnimation(); + final boolean launched = isSuccessfulLaunch(result); + post(new Runnable() { + @Override + public void run() { + unbindCameraPrewarmService(launched); + } + }); } }); } else { // We need to delay starting the activity because ResolverActivity finishes itself if // launched behind lockscreen. - mActivityStarter.startActivity(intent, false /* dismissShade */); + mActivityStarter.startActivity(intent, false /* dismissShade */, + new ActivityStarter.Callback() { + @Override + public void onActivityStarted(int resultCode) { + unbindCameraPrewarmService(isSuccessfulLaunch(resultCode)); + } + }); } } + private static boolean isSuccessfulLaunch(int result) { + return result == ActivityManager.START_SUCCESS + || result == ActivityManager.START_DELIVERED_TO_TOP + || result == ActivityManager.START_TASK_TO_FRONT; + } + public void launchLeftAffordance() { if (mLeftIsVoiceAssist) { launchVoiceAssist(); @@ -412,8 +473,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL if (mPhoneStatusBar.isKeyguardCurrentlySecure()) { AsyncTask.execute(runnable); } else { - mPhoneStatusBar.executeRunnableDismissingKeyguard(runnable, false /* dismissShade */, - false /* afterKeyguardGone */); + mPhoneStatusBar.executeRunnableDismissingKeyguard(runnable, null /* cancelAction */, + false /* dismissShade */, false /* afterKeyguardGone */); } } 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 262d955..3d57d54 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -95,16 +95,16 @@ public class KeyguardBouncer { mShowingSoon = false; } - public void showWithDismissAction(OnDismissAction r) { + public void showWithDismissAction(OnDismissAction r, Runnable cancelAction) { ensureView(); - mKeyguardView.setOnDismissAction(r); + mKeyguardView.setOnDismissAction(r, cancelAction); show(false /* resetSecuritySelection */); } public void hide(boolean destroyView) { cancelShowRunnable(); if (mKeyguardView != null) { - mKeyguardView.setOnDismissAction(null); + mKeyguardView.cancelDismissAction(); mKeyguardView.cleanUp(); } if (destroyView) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java index a712d29..134c579 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java @@ -33,8 +33,6 @@ public final class NavigationBarTransitions extends BarTransitions { private final IStatusBarService mBarService; private boolean mLightsOut; - private boolean mVertical; - private int mRequestedMode; public NavigationBarTransitions(NavigationBarView view) { super(view, R.drawable.nav_background); @@ -43,31 +41,11 @@ public final class NavigationBarTransitions extends BarTransitions { ServiceManager.getService(Context.STATUS_BAR_SERVICE)); } - public void init(boolean isVertical) { - setVertical(isVertical); + public void init() { applyModeBackground(-1, getMode(), false /*animate*/); applyMode(getMode(), false /*animate*/, true /*force*/); } - public void setVertical(boolean isVertical) { - mVertical = isVertical; - transitionTo(mRequestedMode, false /*animate*/); - } - - @Override - public void transitionTo(int mode, boolean animate) { - mRequestedMode = mode; - if (mVertical) { - // translucent mode not allowed when vertical - if (mode == MODE_TRANSLUCENT || mode == MODE_TRANSPARENT) { - mode = MODE_OPAQUE; - } else if (mode == MODE_LIGHTS_OUT_TRANSPARENT) { - mode = MODE_LIGHTS_OUT; - } - } - super.transitionTo(mode, animate); - } - @Override protected void onTransition(int oldMode, int newMode, boolean animate) { super.onTransition(oldMode, newMode, animate); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java index 1dec227..636c511 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -47,7 +47,6 @@ import android.widget.ImageView; import android.widget.LinearLayout; import com.android.systemui.R; -import com.android.systemui.statusbar.BaseStatusBar; import com.android.systemui.statusbar.DelegateViewHelper; import com.android.systemui.statusbar.policy.DeadZone; import com.android.systemui.statusbar.policy.KeyButtonView; @@ -454,7 +453,7 @@ public class NavigationBarView extends LinearLayout { mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone); // force the low profile & disabled states into compliance - mBarTransitions.init(mVertical); + mBarTransitions.init(); setDisabledFlags(mDisabledFlags, true /* force */); setMenuVisibility(mShowMenu, true /* force */); 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 5d48190..4bc317a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -196,6 +196,7 @@ public class NotificationPanelView extends PanelView implements private boolean mCollapsedOnDown; private int mPositionMinSideMargin; private int mLastOrientation = -1; + private boolean mClosingWithAlphaFadeOut; private Runnable mHeadsUpExistenceChangedRunnable = new Runnable() { @Override @@ -527,6 +528,7 @@ public class NotificationPanelView extends PanelView implements protected void flingToHeight(float vel, boolean expand, float target, float collapseSpeedUpFactor, boolean expandBecauseOfFalsing) { mHeadsUpTouchHelper.notifyFling(!expand); + setClosingWithAlphaFadeout(!expand && getFadeoutAlpha() == 1.0f); super.flingToHeight(vel, expand, target, collapseSpeedUpFactor, expandBecauseOfFalsing); } @@ -638,10 +640,9 @@ public class NotificationPanelView extends PanelView implements @Override protected boolean isInContentBounds(float x, float y) { - float yTransformed = y - mNotificationStackScroller.getY(); float stackScrollerX = mNotificationStackScroller.getX(); - return mNotificationStackScroller.isInContentBounds(yTransformed) && stackScrollerX < x - && x < stackScrollerX + mNotificationStackScroller.getWidth(); + return !mNotificationStackScroller.isBelowLastNotification(x - stackScrollerX, y) + && stackScrollerX < x && x < stackScrollerX + mNotificationStackScroller.getWidth(); } private void initDownStates(MotionEvent event) { @@ -1074,8 +1075,12 @@ public class NotificationPanelView extends PanelView implements }; private void animateHeaderSlidingIn() { - mHeaderAnimating = true; - getViewTreeObserver().addOnPreDrawListener(mStartHeaderSlidingIn); + // If the QS is already expanded we don't need to slide in the header as it's already + // visible. + if (!mQsExpanded) { + mHeaderAnimating = true; + getViewTreeObserver().addOnPreDrawListener(mStartHeaderSlidingIn); + } } private void animateHeaderSlidingOut() { @@ -1585,26 +1590,22 @@ public class NotificationPanelView extends PanelView implements } } private void updateNotificationTranslucency() { - float alpha; - if (mExpandingFromHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()) { - alpha = 1f; - } else { - alpha = (getNotificationsTopY() + mNotificationStackScroller.getItemHeight()) - / (mQsMinExpansionHeight + mNotificationStackScroller.getBottomStackPeekSize() - - mNotificationStackScroller.getCollapseSecondCardPadding()); - alpha = Math.max(0, Math.min(alpha, 1)); - alpha = (float) Math.pow(alpha, 0.75); - } - - if (alpha != 1f && mNotificationStackScroller.getLayerType() != LAYER_TYPE_HARDWARE) { - mNotificationStackScroller.setLayerType(LAYER_TYPE_HARDWARE, null); - } else if (alpha == 1f - && mNotificationStackScroller.getLayerType() == LAYER_TYPE_HARDWARE) { - mNotificationStackScroller.setLayerType(LAYER_TYPE_NONE, null); + float alpha = 1f; + if (mClosingWithAlphaFadeOut && !mExpandingFromHeadsUp && !mHeadsUpManager.hasPinnedHeadsUp()) { + alpha = getFadeoutAlpha(); } mNotificationStackScroller.setAlpha(alpha); } + private float getFadeoutAlpha() { + float alpha = (getNotificationsTopY() + mNotificationStackScroller.getItemHeight()) + / (mQsMinExpansionHeight + mNotificationStackScroller.getBottomStackPeekSize() + - mNotificationStackScroller.getCollapseSecondCardPadding()); + alpha = Math.max(0, Math.min(alpha, 1)); + alpha = (float) Math.pow(alpha, 0.75); + return alpha; + } + @Override protected float getOverExpansionAmount() { return mNotificationStackScroller.getCurrentOverScrollAmount(true /* top */); @@ -1934,12 +1935,12 @@ public class NotificationPanelView extends PanelView implements } @Override - public void onSwipingStarted(boolean isRightwardMotion) { - boolean start = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? isRightwardMotion - : !isRightwardMotion; - if (!start) { + public void onSwipingStarted(boolean rightIcon) { + boolean camera = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? !rightIcon + : rightIcon; + if (camera) { mSecureCameraLaunchManager.onSwipingStarted(); - mKeyguardBottomArea.prewarmCamera(); + mKeyguardBottomArea.bindCameraPrewarmService(); } requestDisallowInterceptTouchEvent(true); mOnlyAffordanceInThisMotion = true; @@ -1948,7 +1949,7 @@ public class NotificationPanelView extends PanelView implements @Override public void onSwipingAborted() { - mKeyguardBottomArea.maybeCooldownCamera(); + mKeyguardBottomArea.unbindCameraPrewarmService(false /* launched */); } @Override @@ -2261,6 +2262,12 @@ public class NotificationPanelView extends PanelView implements protected void onClosingFinished() { super.onClosingFinished(); resetVerticalPanelPosition(); + setClosingWithAlphaFadeout(false); + } + + private void setClosingWithAlphaFadeout(boolean closing) { + mClosingWithAlphaFadeOut = closing; + mNotificationStackScroller.forceNoOverlappingRendering(closing); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index 6d35ff0..9d4997c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -777,6 +777,15 @@ public abstract class PanelView extends FrameLayout { public void setExpandedFraction(float frac) { setExpandedHeight(getMaxPanelHeight() * frac); + if (PhoneStatusBar.DEBUG_EMPTY_KEYGUARD + && mStatusBar.getBarState() == StatusBarState.KEYGUARD) { + if (frac == 0.0f) { + Log.i(PhoneStatusBar.TAG, "Panel collapsed! Stacktrace: " + + Log.getStackTraceString(new Throwable())); + } else if (frac == 1.0f) { + mStatusBar.endWindowManagerLogging(); + } + } } public float getExpandedHeight() { @@ -808,6 +817,11 @@ public abstract class PanelView extends FrameLayout { } public void collapse(boolean delayed, float speedUpFactor) { + if (PhoneStatusBar.DEBUG_EMPTY_KEYGUARD + && mStatusBar.getBarState() == StatusBarState.KEYGUARD) { + Log.i(PhoneStatusBar.TAG, "Panel collapsed! Stacktrace: " + + Log.getStackTraceString(new Throwable())); + } if (DEBUG) logf("collapse: " + this); if (mPeekPending || mPeekAnimator != null) { mCollapseAfterPeek = true; 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 ff3f35b..984c201 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -31,6 +31,8 @@ import android.content.ComponentCallbacks2; 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; @@ -61,6 +63,7 @@ import android.os.Message; import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; @@ -182,6 +185,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, HeadsUpManager.OnHeadsUpChangedListener { static final String TAG = "PhoneStatusBar"; public static final boolean DEBUG = BaseStatusBar.DEBUG; + public static final boolean DEBUG_EMPTY_KEYGUARD = true; public static final boolean SPEW = false; public static final boolean DUMPTRUCK = true; // extra dumpsys info public static final boolean DEBUG_GESTURES = false; @@ -229,6 +233,19 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, /** Allow some time inbetween the long press for back and recents. */ private static final int LOCK_TO_APP_GESTURE_TOLERENCE = 200; + private static final boolean ONLY_CORE_APPS; + + static { + boolean onlyCoreApps; + try { + onlyCoreApps = IPackageManager.Stub.asInterface(ServiceManager.getService("package")) + .isOnlyCoreApps(); + } catch (RemoteException e) { + onlyCoreApps = false; + } + ONLY_CORE_APPS = onlyCoreApps; + } + PhoneStatusBarPolicy mIconPolicy; // These are no longer handled by the policy, because we need custom strategies for them @@ -349,6 +366,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (!mUserSetup && mStatusBarView != null) animateCollapseQuickSettings(); } + if (mIconPolicy != null) { + mIconPolicy.setCurrentUserSetup(mUserSetup); + } } }; @@ -554,6 +574,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // Lastly, call to the icon policy to install/update all the icons. mIconPolicy = new PhoneStatusBarPolicy(mContext, mCastController, mHotspotController); + mIconPolicy.setCurrentUserSetup(mUserSetup); mSettingsObserver.onChange(false); // set up mHeadsUpObserver.onChange(true); // set up @@ -1320,7 +1341,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mNotificationPanel.setQsExpansionEnabled(isDeviceProvisioned() && (mUserSetup || mUserSwitcherController == null || !mUserSwitcherController.isSimpleUserSwitcher()) - && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0)); + && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0) + && !ONLY_CORE_APPS); } private void updateNotificationShadeForChildren() { @@ -1827,6 +1849,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } @Override + public void startActivity(Intent intent, boolean dismissShade, Callback callback) { + startActivityDismissingKeyguard(intent, false, dismissShade, callback); + } + + @Override public void preventNextAnimation() { overrideActivityPendingAppTransition(true /* keyguardShowing */); } @@ -1978,6 +2005,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mStatusBarWindowManager.setPanelExpanded(isExpanded); } + public void endWindowManagerLogging() { + mStatusBarWindowManager.setLogState(false); + } + /** * All changes to the status bar and notifications funnel through here and are batched. */ @@ -2024,7 +2055,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } boolean panelsEnabled() { - return (mDisabled1 & StatusBarManager.DISABLE_EXPAND) == 0; + return (mDisabled1 & StatusBarManager.DISABLE_EXPAND) == 0 && !ONLY_CORE_APPS; } void makeExpandedVisible(boolean force) { @@ -2709,7 +2740,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, - final boolean dismissShade) { + boolean dismissShade) { + startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, null /* callback */); + } + + public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, + final boolean dismissShade, final Callback callback) { if (onlyProvisioned && !isDeviceProvisioned()) return; final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( @@ -2719,16 +2755,35 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public void run() { intent.setFlags( Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); - mContext.startActivityAsUser( - intent, new UserHandle(UserHandle.USER_CURRENT)); + int result = ActivityManager.START_CANCELED; + try { + result = ActivityManagerNative.getDefault().startActivityAsUser( + null, mContext.getBasePackageName(), + intent, + intent.resolveTypeIfNeeded(mContext.getContentResolver()), + null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null, + UserHandle.CURRENT.getIdentifier()); + } catch (RemoteException e) { + Log.w(TAG, "Unable to start activity", e); + } overrideActivityPendingAppTransition( keyguardShowing && !afterKeyguardGone); + if (callback != null) { + callback.onActivityStarted(result); + } + } + }; + Runnable cancelRunnable = new Runnable() { + @Override + public void run() { + callback.onActivityStarted(ActivityManager.START_CANCELED); } }; - executeRunnableDismissingKeyguard(runnable, dismissShade, afterKeyguardGone); + executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShade, afterKeyguardGone); } public void executeRunnableDismissingKeyguard(final Runnable runnable, + final Runnable cancelAction, final boolean dismissShade, final boolean afterKeyguardGone) { final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing(); @@ -2755,7 +2810,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } return true; } - }, afterKeyguardGone); + }, cancelAction, afterKeyguardGone); } private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @@ -2815,10 +2870,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } @Override - protected void dismissKeyguardThenExecute(final OnDismissAction action, + protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) { + dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone); + } + + private void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction, boolean afterKeyguardGone) { if (mStatusBarKeyguardViewManager.isShowing()) { - mStatusBarKeyguardViewManager.dismissWithAction(action, afterKeyguardGone); + mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction, + afterKeyguardGone); } else { action.onDismiss(); } @@ -3494,6 +3554,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // Make our window larger and the panel expanded. makeExpandedVisible(true); mNotificationPanel.instantExpand(); + if (DEBUG_EMPTY_KEYGUARD) { + mStatusBarWindowManager.setLogState(true); + } } private void instantCollapseNotificationPanel() { 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 7c10c66..0872e06 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.phone; import android.app.ActivityManagerNative; import android.app.AlarmManager; +import android.app.AlarmManager.AlarmClockInfo; import android.app.IUserSwitchObserver; import android.app.StatusBarManager; import android.bluetooth.BluetoothAdapter; @@ -75,6 +76,7 @@ public class PhoneStatusBarPolicy { private boolean mZenVisible; private boolean mVolumeVisible; + private boolean mCurrentUserSetup; private int mZen; @@ -175,11 +177,12 @@ public class PhoneStatusBarPolicy { } private void updateAlarm() { - final boolean hasAlarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT) != null; + final AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT); + final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0; final boolean zenNone = mZen == Global.ZEN_MODE_NO_INTERRUPTIONS; - mService.setIconVisibility(SLOT_ALARM_CLOCK, hasAlarm); mService.setIcon(SLOT_ALARM_CLOCK, zenNone ? R.drawable.stat_sys_alarm_dim : R.drawable.stat_sys_alarm, 0, null); + mService.setIconVisibility(SLOT_ALARM_CLOCK, mCurrentUserSetup && hasAlarm); } private final void updateSimState(Intent intent) { @@ -391,4 +394,10 @@ public class PhoneStatusBarPolicy { mKeyguardVisible = visible; updateManagedProfile(); } + + public void setCurrentUserSetup(boolean userSetup) { + if (mCurrentUserSetup == userSetup) return; + mCurrentUserSetup = userSetup; + updateAlarm(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java index aa499ad..b7e675d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java @@ -20,12 +20,14 @@ import android.content.Context; import android.content.res.Resources; import android.util.AttributeSet; import android.util.EventLog; +import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityEvent; import com.android.systemui.EventLogTags; import com.android.systemui.R; +import com.android.systemui.statusbar.StatusBarState; public class PhoneStatusBarView extends PanelBar { private static final String TAG = "PhoneStatusBarView"; @@ -108,7 +110,11 @@ public class PhoneStatusBarView extends PanelBar { @Override public void onAllPanelsCollapsed() { super.onAllPanelsCollapsed(); - + if (PhoneStatusBar.DEBUG_EMPTY_KEYGUARD + && mBar.getBarState() == StatusBarState.KEYGUARD) { + Log.i(PhoneStatusBar.TAG, "Panel collapsed! Stacktrace: " + + Log.getStackTraceString(new Throwable())); + } // Close the status bar in the next frame so we can show the end of the animation. postOnAnimation(new Runnable() { @Override 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 45da297..a268077 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java @@ -20,10 +20,14 @@ 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; import android.view.ViewGroup; import android.view.animation.AnimationUtils; @@ -53,6 +57,8 @@ public class StatusBarIconController { public static final long DEFAULT_TINT_ANIMATION_DURATION = 120; + public static final String ICON_BLACKLIST = "icon_blacklist"; + private Context mContext; private PhoneStatusBar mPhoneStatusBar; private Interpolator mLinearOutSlowIn; @@ -89,6 +95,8 @@ public class StatusBarIconController { private long mTransitionDeferringStartTime; private long mTransitionDeferringDuration; + private final ArraySet<String> mIconBlacklist; + private final Runnable mTransitionDeferringDoneRunnable = new Runnable() { @Override public void run() { @@ -118,7 +126,12 @@ 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); } public void updateResources() { @@ -130,11 +143,12 @@ public class StatusBarIconController { } public void addSystemIcon(String slot, int index, int viewIndex, StatusBarIcon icon) { - StatusBarIconView view = new StatusBarIconView(mContext, slot, null); + boolean blocked = mIconBlacklist.contains(slot); + StatusBarIconView view = new StatusBarIconView(mContext, slot, null, blocked); view.set(icon); mStatusIcons.addView(view, viewIndex, new LinearLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize)); - view = new StatusBarIconView(mContext, slot, null); + view = new StatusBarIconView(mContext, slot, null, blocked); view.set(icon); mStatusIconsKeyguard.addView(view, viewIndex, new LinearLayout.LayoutParams( ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize)); @@ -414,4 +428,43 @@ 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); + ArraySet<String> ret = new ArraySet<String>(); + if (blackListStr != null) { + String[] blacklist = blackListStr.split(","); + for (String slot : blacklist) { + if (!TextUtils.isEmpty(slot)) { + ret.add(slot); + } + } + } + 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 0caf51a..6cb890a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -126,10 +126,11 @@ public class StatusBarKeyguardViewManager { updateStates(); } - public void dismissWithAction(OnDismissAction r, boolean afterKeyguardGone) { + public void dismissWithAction(OnDismissAction r, Runnable cancelAction, + boolean afterKeyguardGone) { if (mShowing) { if (!afterKeyguardGone) { - mBouncer.showWithDismissAction(r); + mBouncer.showWithDismissAction(r, cancelAction); } else { mBouncer.show(false /* resetSecuritySelection */); mAfterKeyguardGoneAction = r; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java index de42643..58017d0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java @@ -21,6 +21,7 @@ import android.content.pm.ActivityInfo; import android.content.res.Resources; import android.graphics.PixelFormat; import android.os.SystemProperties; +import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; @@ -31,6 +32,8 @@ import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.statusbar.BaseStatusBar; import com.android.systemui.statusbar.StatusBarState; +import java.lang.reflect.Field; + /** * Encapsulates all logic for the status bar window state management. */ @@ -45,6 +48,7 @@ public class StatusBarWindowManager { private final boolean mKeyguardScreenRotation; private final State mCurrentState = new State(); + private boolean mLogState; public StatusBarWindowManager(Context context) { mContext = context; @@ -129,9 +133,7 @@ public class StatusBarWindowManager { } private void applyHeight(State state) { - boolean expanded = !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded() - || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing - || state.headsUpShowing); + boolean expanded = isExpanded(state); if (expanded) { mLpChanged.height = ViewGroup.LayoutParams.MATCH_PARENT; } else { @@ -139,6 +141,12 @@ public class StatusBarWindowManager { } } + private boolean isExpanded(State state) { + return !state.forceCollapsed && (state.isKeyguardShowingAndNotOccluded() + || state.panelVisible || state.keyguardFadingAway || state.bouncerShowing + || state.headsUpShowing); + } + private void applyFitsSystemWindows(State state) { mStatusBarView.setFitsSystemWindows(!state.isKeyguardShowingAndNotOccluded()); } @@ -176,6 +184,9 @@ public class StatusBarWindowManager { applyFitsSystemWindows(state); applyModalFlag(state); if (mLp.copyFrom(mLpChanged) != 0) { + if (PhoneStatusBar.DEBUG_EMPTY_KEYGUARD && mLogState) { + logCurrentState(); + } mWindowManager.updateViewLayout(mStatusBarView, mLp); } } @@ -272,6 +283,21 @@ public class StatusBarWindowManager { apply(mCurrentState); } + public void setLogState(boolean logState) { + mLogState = logState; + if (logState) { + Log.w(PhoneStatusBar.TAG, "===== Started logging WM state changes ====="); + logCurrentState(); + } else { + Log.w(PhoneStatusBar.TAG, "===== Finished logging WM state changes ====="); + } + } + + private void logCurrentState() { + Log.i(PhoneStatusBar.TAG, mCurrentState.toString() + + "\n Expanded: " + isExpanded(mCurrentState)); + } + private static class State { boolean keyguardShowing; boolean keyguardOccluded; @@ -294,5 +320,31 @@ public class StatusBarWindowManager { private boolean isKeyguardShowingAndNotOccluded() { return keyguardShowing && !keyguardOccluded; } + + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + String newLine = "\n"; + result.append("Window State {"); + result.append(newLine); + + Field[] fields = this.getClass().getDeclaredFields(); + + // Print field names paired with their values + for (Field field : fields) { + result.append(" "); + try { + result.append(field.getName()); + result.append(": "); + //requires access to private field: + result.append(field.get(this)); + } catch (IllegalAccessException ex) { + } + result.append(newLine); + } + result.append("}"); + + return result.toString(); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java index 3b91751..6a8f8ee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java @@ -171,7 +171,6 @@ public class StatusBarWindowView extends FrameLayout { if (mNotificationPanel.isFullyExpanded() && mStackScrollLayout.getVisibility() == View.VISIBLE && mService.getBarState() == StatusBarState.KEYGUARD - && !mService.isQsExpanded() && !mService.isBouncerShowing()) { intercept = mDragDownHelper.onInterceptTouchEvent(ev); // wake up on a touch down event, if dozing @@ -195,7 +194,7 @@ public class StatusBarWindowView extends FrameLayout { @Override public boolean onTouchEvent(MotionEvent ev) { boolean handled = false; - if (mService.getBarState() == StatusBarState.KEYGUARD && !mService.isQsExpanded()) { + if (mService.getBarState() == StatusBarState.KEYGUARD) { handled = mDragDownHelper.onTouchEvent(ev); } if (!handled) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java index 7f52191..e618cb8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CallbackHandler.java @@ -124,17 +124,16 @@ public class CallbackHandler extends Handler implements EmergencyListener, Signa @Override public void setMobileDataIndicators(final IconState statusIcon, final IconState qsIcon, - final int darkStatusIcon, final int statusType, final int qsType, - final boolean activityIn, final boolean activityOut, - final String typeContentDescription, final String description, final boolean isWide, - final int subId) { + final int statusType, final int qsType,final boolean activityIn, + final boolean activityOut, final String typeContentDescription, + final String description, final boolean isWide, final int subId) { post(new Runnable() { @Override public void run() { for (SignalCallback signalCluster : mSignalCallbacks) { - signalCluster.setMobileDataIndicators(statusIcon, qsIcon, darkStatusIcon, - statusType, qsType, activityIn, activityOut, typeContentDescription, - description, isWide, subId); + signalCluster.setMobileDataIndicators(statusIcon, qsIcon, statusType, qsType, + activityIn, activityOut, typeContentDescription, description, isWide, + subId); } } }); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index 0d59953..686e24c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -117,7 +117,7 @@ public class MobileSignalController extends SignalController< public void setCarrierNetworkChangeMode(boolean carrierNetworkChangeMode) { mCurrentState.carrierNetworkChangeMode = carrierNetworkChangeMode; - notifyListenersIfNecessary(); + updateTelephony(); } /** @@ -220,13 +220,9 @@ public class MobileSignalController extends SignalController< && mCurrentState.activityOut; showDataIcon &= mCurrentState.isDefault; int typeIcon = showDataIcon ? icons.mDataType : 0; - mCallbackHandler.setMobileDataIndicators(statusIcon, qsIcon, getCurrentDarkIconId(), - typeIcon, qsTypeIcon, activityIn, activityOut, dataContentDescription, description, - icons.mIsWide, mSubscriptionInfo.getSubscriptionId()); - } - - private int getCurrentDarkIconId() { - return getCurrentIconId(false /* light */); + mCallbackHandler.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon, + activityIn, activityOut, dataContentDescription, description, icons.mIsWide, + mSubscriptionInfo.getSubscriptionId()); } @Override @@ -276,7 +272,7 @@ public class MobileSignalController extends SignalController< } private boolean isCarrierNetworkChangeActive() { - return !hasService() && mCurrentState.carrierNetworkChangeMode; + return mCurrentState.carrierNetworkChangeMode; } public void handleBroadcast(Intent intent) { @@ -478,17 +474,8 @@ public class MobileSignalController extends SignalController< int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, int discContentDesc, int dataContentDesc, int dataType, boolean isWide, int qsDataType) { - this(name, sbIcons, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, - sbDiscState, sbDiscState, qsDiscState, discContentDesc, dataContentDesc, - dataType, isWide, qsDataType); - } - - public MobileIconGroup(String name, int[][] sbIcons, int[][] sbDarkIcons, int[][] qsIcons, - int[] contentDesc, int sbNullState, int qsNullState, int sbDiscState, - int sbDarkDiscState, int qsDiscState, int discContentDesc, int dataContentDesc, - int dataType, boolean isWide, int qsDataType) { - super(name, sbIcons, sbDarkIcons, qsIcons, contentDesc, sbNullState, qsNullState, - sbDiscState, sbDarkDiscState, qsDiscState, discContentDesc); + super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState, + qsDiscState, discContentDesc); mDataContentDescription = dataContentDesc; mDataType = dataType; mIsWide = isWide; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java index 070ca63..38656ee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java @@ -38,9 +38,9 @@ public interface NetworkController { void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon, boolean activityIn, boolean activityOut, String description); - void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int darkStatusIcon, - int statusType, int qsType, boolean activityIn, boolean activityOut, - String typeContentDescription, String description, boolean isWide, int subId); + void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, + int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, + String description, boolean isWide, int subId); void setSubs(List<SubscriptionInfo> subs); void setNoSims(boolean show); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java index 4269c19..93d0ec3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.policy; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Bundle; @@ -138,14 +139,14 @@ public class PreviewInflater { public static boolean wouldLaunchResolverActivity(Context ctx, Intent intent, int currentUserId) { - return getTargetPackage(ctx, intent, currentUserId) == null; + return getTargetActivityInfo(ctx, intent, currentUserId) == null; } /** - * @return the target package of the intent it resolves to a specific package or {@code null} if - * it resolved to the resolver activity + * @return the target activity info of the intent it resolves to a specific package or + * {@code null} if it resolved to the resolver activity */ - public static String getTargetPackage(Context ctx, Intent intent, + public static ActivityInfo getTargetActivityInfo(Context ctx, Intent intent, int currentUserId) { PackageManager packageManager = ctx.getPackageManager(); final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser( @@ -158,7 +159,7 @@ public class PreviewInflater { if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) { return null; } else { - return resolved.activityInfo.packageName; + return resolved.activityInfo; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java index 83a7d3d..dce889f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalCallbackAdapter.java @@ -35,10 +35,9 @@ public class SignalCallbackAdapter implements SignalCallback { } @Override - public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, - int darkStatusIcon, int statusType, int qsType, boolean activityIn, - boolean activityOut, String typeContentDescription, String description, - boolean isWide, int subId) { + public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, + int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, + String description, boolean isWide, int subId) { } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java index e6ca646..5e9447e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java @@ -133,22 +133,10 @@ public abstract class SignalController<T extends SignalController.State, * Gets the signal icon for SB based on current state of connected, enabled, and level. */ public int getCurrentIconId() { - return getCurrentIconId(true /* light */); - } - - protected int getCurrentIconId(boolean light) { if (mCurrentState.connected) { - if (light) { - return getIcons().mSbIcons[mCurrentState.inetCondition][mCurrentState.level]; - } else { - return getIcons().mSbDarkIcons[mCurrentState.inetCondition][mCurrentState.level]; - } + return getIcons().mSbIcons[mCurrentState.inetCondition][mCurrentState.level]; } else if (mCurrentState.enabled) { - if (light) { - return getIcons().mSbDiscState; - } else { - return getIcons().mSbDarkDiscState; - } + return getIcons().mSbDiscState; } else { return getIcons().mSbNullState; } @@ -229,13 +217,11 @@ public abstract class SignalController<T extends SignalController.State, */ static class IconGroup { final int[][] mSbIcons; - final int[][] mSbDarkIcons; final int[][] mQsIcons; final int[] mContentDesc; final int mSbNullState; final int mQsNullState; final int mSbDiscState; - final int mSbDarkDiscState; final int mQsDiscState; final int mDiscContentDesc; // For logging. @@ -244,22 +230,13 @@ public abstract class SignalController<T extends SignalController.State, public IconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc, int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, int discContentDesc) { - this(name, sbIcons, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, - sbDiscState, sbDiscState, qsDiscState, discContentDesc); - } - - public IconGroup(String name, int[][] sbIcons, int[][] sbDarkIcons, int[][] qsIcons, - int[] contentDesc, int sbNullState, int qsNullState, int sbDiscState, - int sbDarkDiscState, int qsDiscState, int discContentDesc) { mName = name; mSbIcons = sbIcons; - mSbDarkIcons = sbDarkIcons; mQsIcons = qsIcons; mContentDesc = contentDesc; mSbNullState = sbNullState; mQsNullState = qsNullState; mSbDiscState = sbDiscState; - mSbDarkDiscState = sbDarkDiscState; mQsDiscState = qsDiscState; mDiscContentDesc = discContentDesc; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java index fa4d464..8a27653 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java @@ -73,24 +73,15 @@ class TelephonyIcons { { R.drawable.stat_sys_signal_carrier_network_change_animation, R.drawable.stat_sys_signal_carrier_network_change_animation, R.drawable.stat_sys_signal_carrier_network_change_animation, + R.drawable.stat_sys_signal_carrier_network_change_animation, R.drawable.stat_sys_signal_carrier_network_change_animation }, { R.drawable.stat_sys_signal_carrier_network_change_animation, R.drawable.stat_sys_signal_carrier_network_change_animation, R.drawable.stat_sys_signal_carrier_network_change_animation, + R.drawable.stat_sys_signal_carrier_network_change_animation, R.drawable.stat_sys_signal_carrier_network_change_animation } }; - static final int[][] TELEPHONY_CARRIER_NETWORK_CHANGE_DARK = { - { R.drawable.stat_sys_signal_dark_carrier_network_change_animation, - R.drawable.stat_sys_signal_dark_carrier_network_change_animation, - R.drawable.stat_sys_signal_dark_carrier_network_change_animation, - R.drawable.stat_sys_signal_dark_carrier_network_change_animation }, - { R.drawable.stat_sys_signal_dark_carrier_network_change_animation, - R.drawable.stat_sys_signal_dark_carrier_network_change_animation, - R.drawable.stat_sys_signal_dark_carrier_network_change_animation, - R.drawable.stat_sys_signal_dark_carrier_network_change_animation } - }; - static final int[][] QS_TELEPHONY_CARRIER_NETWORK_CHANGE = { { R.drawable.ic_qs_signal_carrier_network_change_animation, R.drawable.ic_qs_signal_carrier_network_change_animation, @@ -216,8 +207,6 @@ class TelephonyIcons { static final int ICON_1X = R.drawable.stat_sys_data_fully_connected_1x; static final int ICON_CARRIER_NETWORK_CHANGE = R.drawable.stat_sys_signal_carrier_network_change_animation; - static final int ICON_CARRIER_NETWORK_CHANGE_DARK = - R.drawable.stat_sys_signal_dark_carrier_network_change_animation; static final int QS_ICON_LTE = R.drawable.ic_qs_signal_lte; static final int QS_ICON_3G = R.drawable.ic_qs_signal_3g; @@ -229,12 +218,10 @@ class TelephonyIcons { static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup( "CARRIER_NETWORK_CHANGE", TelephonyIcons.TELEPHONY_CARRIER_NETWORK_CHANGE, - TelephonyIcons.TELEPHONY_CARRIER_NETWORK_CHANGE_DARK, TelephonyIcons.QS_TELEPHONY_CARRIER_NETWORK_CHANGE, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, 0, 0, TelephonyIcons.ICON_CARRIER_NETWORK_CHANGE, - TelephonyIcons.ICON_CARRIER_NETWORK_CHANGE_DARK, TelephonyIcons.QS_ICON_CARRIER_NETWORK_CHANGE, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], R.string.accessibility_carrier_network_change_mode, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index e73c593..d8f6bcd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -225,6 +225,7 @@ public class NotificationStackScrollLayout extends ViewGroup private HeadsUpManager mHeadsUpManager; private boolean mTrackingHeadsUp; private ScrimController mScrimController; + private boolean mForceNoOverlappingRendering; public NotificationStackScrollLayout(Context context) { this(context, null); @@ -811,8 +812,7 @@ public class NotificationStackScrollLayout extends ViewGroup } handleEmptySpaceClick(ev); boolean expandWantsIt = false; - if (mIsExpanded && !mSwipingInProgress && !mOnlyScrollingInThisMotion - && isScrollingEnabled()) { + if (mIsExpanded && !mSwipingInProgress && !mOnlyScrollingInThisMotion) { if (isCancelOrUp) { mExpandHelper.onlyObserveMovements(false); } @@ -1566,7 +1566,7 @@ public class NotificationStackScrollLayout extends ViewGroup initDownStates(ev); handleEmptySpaceClick(ev); boolean expandWantsIt = false; - if (!mSwipingInProgress && !mOnlyScrollingInThisMotion && isScrollingEnabled()) { + if (!mSwipingInProgress && !mOnlyScrollingInThisMotion) { expandWantsIt = mExpandHelper.onInterceptTouchEvent(ev); } boolean scrollWantsIt = false; @@ -1655,8 +1655,13 @@ public class NotificationStackScrollLayout extends ViewGroup * @return Whether an animation was generated. */ private boolean generateRemoveAnimation(View child) { + if (mAddedHeadsUpChildren.contains(child)) { + removeChildFromHeadsUpChangeAnimations(child); + mAddedHeadsUpChildren.remove(child); + return false; + } if (mIsExpanded && mAnimationsEnabled && !isChildInInvisibleGroup(child)) { - if (!mChildrenToAddAnimated.contains(child) && !mAddedHeadsUpChildren.contains(child)) { + if (!mChildrenToAddAnimated.contains(child)) { // Generate Animations mChildrenToRemoveAnimated.add(child); mNeedsAnimation = true; @@ -1664,10 +1669,6 @@ public class NotificationStackScrollLayout extends ViewGroup } else { mChildrenToAddAnimated.remove(child); mFromMoreCardAdditions.remove(child); - boolean remove = mAddedHeadsUpChildren.remove(child); - if (remove) { - removeChildFromHeadsUpChangeAnimations(child); - } return false; } } @@ -2266,11 +2267,11 @@ public class NotificationStackScrollLayout extends ViewGroup private void updateScrollPositionOnExpandInBottom(ExpandableView view) { if (view instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) view; - if (row.isUserLocked()) { + if (row.isUserLocked() && row != getFirstChildNotGone()) { // We are actually expanding this view float endPosition = row.getTranslationY() + row.getActualHeight(); int stackEnd = mMaxLayoutHeight - mBottomStackPeekSize - - mBottomStackSlowDownHeight; + mBottomStackSlowDownHeight + (int) mStackTranslation; if (endPosition > stackEnd) { mOwnScrollY += endPosition - stackEnd; mDisallowScrollingInThisMotion = true; @@ -2613,7 +2614,7 @@ public class NotificationStackScrollLayout extends ViewGroup } } - private boolean isBelowLastNotification(float touchX, float touchY) { + public boolean isBelowLastNotification(float touchX, float touchY) { int childCount = getChildCount(); for (int i = childCount - 1; i >= 0; i--) { ExpandableView child = (ExpandableView) getChildAt(i); @@ -2639,7 +2640,7 @@ public class NotificationStackScrollLayout extends ViewGroup } } } - return touchY > mIntrinsicPadding; + return touchY > mTopPadding + mStackTranslation; } private void updateExpandButtons() { @@ -2731,6 +2732,15 @@ public class NotificationStackScrollLayout extends ViewGroup mScrimController = scrimController; } + public void forceNoOverlappingRendering(boolean force) { + mForceNoOverlappingRendering = force; + } + + @Override + public boolean hasOverlappingRendering() { + return !mForceNoOverlappingRendering && super.hasOverlappingRendering(); + } + /** * A listener that is notified when some child locations might have changed. */ diff --git a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java index 90c1897..9f593fc 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/QsTuner.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.provider.Settings.Secure; +import android.text.TextUtils; import android.util.Log; import android.view.DragEvent; import android.view.LayoutInflater; @@ -32,7 +33,6 @@ import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnDragListener; -import android.view.View.OnLongClickListener; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.widget.EditText; @@ -47,6 +47,7 @@ import com.android.systemui.qs.QSTile.ResourceIcon; import com.android.systemui.qs.QSTileView; import com.android.systemui.qs.tiles.IntentTile; import com.android.systemui.statusbar.phone.QSTileHost; +import com.android.systemui.statusbar.policy.SecurityController; import java.util.List; @@ -174,7 +175,7 @@ public class QsTuner extends Fragment implements Callback { public CustomHost(Context context) { super(context, null, null, null, null, null, null, null, null, null, - null, null, null); + null, null, new BlankSecurityController()); } @Override @@ -215,15 +216,8 @@ public class QsTuner extends Fragment implements Callback { } private void setTiles(List<String> tiles) { - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < tiles.size(); i++) { - if (builder.length() != 0) { - builder.append(','); - } - builder.append(tiles.get(i)); - } - Secure.putStringForUser(getContext().getContentResolver(), - TILES_SETTING, builder.toString(), mUserTracker.getCurrentUserId()); + Secure.putStringForUser(getContext().getContentResolver(), TILES_SETTING, + TextUtils.join(",", tiles), mUserTracker.getCurrentUserId()); } public void showAddDialog() { @@ -282,6 +276,45 @@ public class QsTuner extends Fragment implements Callback { } return true; } + + private static class BlankSecurityController implements SecurityController { + @Override + public boolean hasDeviceOwner() { + return false; + } + + @Override + public boolean hasProfileOwner() { + return false; + } + + @Override + public String getDeviceOwnerName() { + return null; + } + + @Override + public String getProfileOwnerName() { + return null; + } + + @Override + public boolean isVpnEnabled() { + return false; + } + + @Override + public void onUserSwitched(int newUserId) { + } + + @Override + public void addCallback(SecurityControllerCallback callback) { + } + + @Override + public void removeCallback(SecurityControllerCallback callback) { + } + } } private static class DraggableTile extends QSTile<QSTile.State> diff --git a/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java new file mode 100644 index 0000000..8158a68 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java @@ -0,0 +1,58 @@ +/* + * 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.preference.SwitchPreference; +import android.provider.Settings; +import android.text.TextUtils; +import android.util.AttributeSet; + +import com.android.systemui.statusbar.phone.StatusBarIconController; + +import java.util.Set; + +public class StatusBarSwitch extends SwitchPreference { + + public StatusBarSwitch(Context context, AttributeSet attrs) { + super(context, attrs); + setChecked(!StatusBarIconController.isBlocked(getContext(), 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); + } + } else { + if (blacklist != null && blacklist.remove(getKey())) { + setList(blacklist); + } + } + return true; + } + + private void setList(Set<String> blacklist) { + ContentResolver contentResolver = getContext().getContentResolver(); + Settings.Secure.putString(contentResolver, StatusBarIconController.ICON_BLACKLIST, + TextUtils.join(",", blacklist)); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingSecondaryUserActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingSecondaryUserActivity.java new file mode 100644 index 0000000..9ce771b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingSecondaryUserActivity.java @@ -0,0 +1,96 @@ +/* + * 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.usb; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.UserInfo; +import android.hardware.usb.UsbManager; +import android.os.Bundle; +import android.os.SystemProperties; +import android.os.UserHandle; +import android.os.UserManager; + +import com.android.internal.app.AlertActivity; +import com.android.internal.app.AlertController; +import com.android.systemui.R; + +public class UsbDebuggingSecondaryUserActivity extends AlertActivity + implements DialogInterface.OnClickListener { + private UsbDisconnectedReceiver mDisconnectedReceiver; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + if (SystemProperties.getInt("service.adb.tcp.port", 0) == 0) { + mDisconnectedReceiver = new UsbDisconnectedReceiver(this); + } + + final AlertController.AlertParams ap = mAlertParams; + ap.mTitle = getString(R.string.usb_debugging_secondary_user_title); + UserInfo user = UserManager.get(this).getUserInfo(UserHandle.USER_OWNER); + ap.mMessage = getString(R.string.usb_debugging_secondary_user_message, user.name); + ap.mPositiveButtonText = getString(android.R.string.ok); + ap.mPositiveButtonListener = this; + + setupAlert(); + } + + private class UsbDisconnectedReceiver extends BroadcastReceiver { + private final Activity mActivity; + public UsbDisconnectedReceiver(Activity activity) { + mActivity = activity; + } + + @Override + public void onReceive(Context content, Intent intent) { + String action = intent.getAction(); + if (UsbManager.ACTION_USB_STATE.equals(action)) { + boolean connected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false); + if (!connected) { + mActivity.finish(); + } + } + } + } + + @Override + public void onStart() { + super.onStart(); + + IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_STATE); + registerReceiver(mDisconnectedReceiver, filter); + } + + @Override + protected void onStop() { + if (mDisconnectedReceiver != null) { + unregisterReceiver(mDisconnectedReceiver); + } + super.onStop(); + } + + @Override + public void onClick(DialogInterface dialog, int which) { + finish(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java index 09f7074..310a64c 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java @@ -726,11 +726,6 @@ public class VolumeDialog { } row.slider.setProgress(newProgress); } - if (mAutomute && mShowing) { - if (vlevel == 0 && !row.ss.muted && row.stream == AudioManager.STREAM_MUSIC) { - mController.setStreamMute(row.stream, true); - } - } } } @@ -934,16 +929,6 @@ public class VolumeDialog { final int userLevel = getImpliedLevel(seekBar, progress); if (mRow.ss.level != userLevel || mRow.ss.muted && userLevel > 0) { mRow.userAttempt = SystemClock.uptimeMillis(); - if (mAutomute) { - if (mRow.stream != AudioManager.STREAM_RING) { - if (userLevel > 0 && mRow.ss.muted) { - mController.setStreamMute(mRow.stream, false); - } - if (userLevel == 0 && mRow.ss.muteSupported && !mRow.ss.muted) { - mController.setStreamMute(mRow.stream, true); - } - } - } if (mRow.requestedLevel != userLevel) { mController.setStreamVolume(mRow.stream, userLevel); mRow.requestedLevel = userLevel; diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java index 6d67d11..3f6294d 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java +++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java @@ -126,8 +126,12 @@ public class ZenFooter extends LinearLayout { : null; Util.setText(mSummaryLine1, line1); - final String line2 = ZenModeConfig.getConditionSummary(mContext, mConfig, - mController.getCurrentUser(), true /*shortVersion*/); + final boolean isForever = mConfig != null && mConfig.manualRule != null + && mConfig.manualRule.conditionId == null; + final String line2 = + isForever ? mContext.getString(com.android.internal.R.string.zen_mode_forever_dnd) + : ZenModeConfig.getConditionSummary(mContext, mConfig, mController.getCurrentUser(), + true /*shortVersion*/); Util.setText(mSummaryLine2, line2); } |