diff options
Diffstat (limited to 'packages/SystemUI/src/com/android/systemui')
48 files changed, 1624 insertions, 384 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java b/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java index 4717a0b..247e965 100644 --- a/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryLevelTextView.java @@ -17,6 +17,7 @@ package com.android.systemui; import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.BatteryStateRegistar; import android.content.Context; import android.content.res.Configuration; @@ -28,7 +29,10 @@ import java.text.NumberFormat; public class BatteryLevelTextView extends TextView implements BatteryController.BatteryStateChangeCallback{ - private BatteryController mBatteryController; + + private BatteryStateRegistar mBatteryStateRegistar; + private boolean mBatteryPresent; + private boolean mBatteryCharging; private boolean mForceShow; private boolean mAttached; @@ -38,7 +42,9 @@ public class BatteryLevelTextView extends TextView implements public BatteryLevelTextView(Context context, AttributeSet attrs) { super(context, attrs); - mRequestedVisibility = getVisibility(); + // setBatteryStateRegistar (if called) will made the view visible and ready to be hidden + // if the view shouldn't be displayed. Otherwise this view should be hidden from start. + mRequestedVisibility = GONE; } public void setForceShown(boolean forceShow) { @@ -46,10 +52,11 @@ public class BatteryLevelTextView extends TextView implements updateVisibility(); } - public void setBatteryController(BatteryController batteryController) { - mBatteryController = batteryController; + public void setBatteryStateRegistar(BatteryStateRegistar batteryStateRegistar) { + mRequestedVisibility = VISIBLE; + mBatteryStateRegistar = batteryStateRegistar; if (mAttached) { - mBatteryController.addStateChangedCallback(this); + mBatteryStateRegistar.addStateChangedCallback(this); } } @@ -69,10 +76,12 @@ public class BatteryLevelTextView extends TextView implements } @Override - public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { + public void onBatteryLevelChanged(boolean present, int level, boolean pluggedIn, + boolean charging) { String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0); setText(percentage); - if (mBatteryCharging != charging) { + if (mBatteryPresent != present || mBatteryCharging != charging) { + mBatteryPresent = present; mBatteryCharging = charging; updateVisibility(); } @@ -94,8 +103,8 @@ public class BatteryLevelTextView extends TextView implements public void onAttachedToWindow() { super.onAttachedToWindow(); - if (mBatteryController != null) { - mBatteryController.addStateChangedCallback(this); + if (mBatteryStateRegistar != null) { + mBatteryStateRegistar.addStateChangedCallback(this); } mAttached = true; @@ -106,21 +115,22 @@ public class BatteryLevelTextView extends TextView implements super.onDetachedFromWindow(); mAttached = false; - if (mBatteryController != null) { - mBatteryController.removeStateChangedCallback(this); + if (mBatteryStateRegistar != null) { + mBatteryStateRegistar.removeStateChangedCallback(this); } } private void updateVisibility() { - boolean showNextPercent = mPercentMode == BatteryController.PERCENTAGE_MODE_OUTSIDE - || (mBatteryCharging && mPercentMode == BatteryController.PERCENTAGE_MODE_INSIDE); + boolean showNextPercent = mBatteryPresent && ( + mPercentMode == BatteryController.PERCENTAGE_MODE_OUTSIDE + || (mBatteryCharging && mPercentMode == BatteryController.PERCENTAGE_MODE_INSIDE)); if (mStyle == BatteryController.STYLE_GONE) { showNextPercent = false; } else if (mStyle == BatteryController.STYLE_TEXT) { showNextPercent = true; } - if (showNextPercent || mForceShow) { + if (mBatteryStateRegistar != null && (showNextPercent || mForceShow)) { super.setVisibility(mRequestedVisibility); } else { super.setVisibility(GONE); diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java index 244b7f7..e606156 100755 --- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java @@ -17,6 +17,7 @@ package com.android.systemui; import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.BatteryStateRegistar; import android.animation.ArgbEvaluator; import android.content.BroadcastReceiver; @@ -73,6 +74,7 @@ public class BatteryMeterView extends View implements DemoMode, private final Path mClipPath = new Path(); private final Path mTextPath = new Path(); + private BatteryStateRegistar mBatteryStateRegistar; private BatteryController mBatteryController; private boolean mPowerSaveEnabled; @@ -92,7 +94,7 @@ public class BatteryMeterView extends View implements DemoMode, private BatteryMeterDrawable mBatteryMeterDrawable; private int mIconTint = Color.WHITE; - private class BatteryTracker extends BroadcastReceiver { + protected class BatteryTracker extends BroadcastReceiver { public static final int UNKNOWN_LEVEL = -1; // current battery status @@ -128,7 +130,6 @@ public class BatteryMeterView extends View implements DemoMode, technology = intent.getStringExtra(BatteryManager.EXTRA_TECHNOLOGY); voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0); temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0); - setContentDescription( context.getString(R.string.accessibility_battery_level, level)); if (mBatteryMeterDrawable != null) { @@ -193,7 +194,9 @@ public class BatteryMeterView extends View implements DemoMode, // preload the battery level mTracker.onReceive(getContext(), sticky); } - mBatteryController.addStateChangedCallback(this); + if (mBatteryStateRegistar != null) { + mBatteryStateRegistar.addStateChangedCallback(this); + } mAttached = true; } @@ -203,7 +206,9 @@ public class BatteryMeterView extends View implements DemoMode, mAttached = false; getContext().unregisterReceiver(mTracker); - mBatteryController.removeStateChangedCallback(this); + if (mBatteryStateRegistar != null) { + mBatteryStateRegistar.removeStateChangedCallback(this); + } } public BatteryMeterView(Context context) { @@ -279,20 +284,28 @@ public class BatteryMeterView extends View implements DemoMode, width = height; } else if (mMeterMode == BatteryMeterMode.BATTERY_METER_TEXT) { onSizeChanged(width, height, 0, 0); // Force a size changed event - } else if (mMeterMode.compareTo(BatteryMeterMode.BATTERY_METER_ICON_LANDSCAPE) == 0) { + } else if (mMeterMode == BatteryMeterMode.BATTERY_METER_ICON_LANDSCAPE) { width = (int)(height * 1.2f); } setMeasuredDimension(width, height); } + public void setBatteryStateRegistar(BatteryStateRegistar batteryStateRegistar) { + mBatteryStateRegistar = batteryStateRegistar; + if (!mAttached) { + mBatteryStateRegistar.addStateChangedCallback(this); + } + } + public void setBatteryController(BatteryController batteryController) { mBatteryController = batteryController; mPowerSaveEnabled = mBatteryController.isPowerSave(); } @Override - public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { + public void onBatteryLevelChanged(boolean present, int level, boolean pluggedIn, + boolean charging) { // TODO: Use this callback instead of own broadcast receiver. } @@ -742,9 +755,7 @@ public class BatteryMeterView extends View implements DemoMode, } private float[] loadBoltPoints(Resources res) { - final int[] pts = res.getIntArray((mHorizontal - ? R.array.batterymeter_inverted_bolt_points - : R.array.batterymeter_bolt_points)); + final int[] pts = res.getIntArray(getBoltPointsArrayResource()); int maxX = 0, maxY = 0; for (int i = 0; i < pts.length; i += 2) { maxX = Math.max(maxX, pts[i]); @@ -757,6 +768,12 @@ public class BatteryMeterView extends View implements DemoMode, } return ptsF; } + + protected int getBoltPointsArrayResource() { + return mHorizontal + ? R.array.batterymeter_inverted_bolt_points + : R.array.batterymeter_bolt_points; + } } protected class CircleBatteryMeterDrawable implements BatteryMeterDrawable { @@ -858,7 +875,7 @@ public class BatteryMeterView extends View implements DemoMode, } private float[] loadBoltPoints(Resources res) { - final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points); + final int[] pts = res.getIntArray(getBoltPointsArrayResource()); int maxX = 0, maxY = 0; for (int i = 0; i < pts.length; i += 2) { maxX = Math.max(maxX, pts[i]); @@ -872,6 +889,10 @@ public class BatteryMeterView extends View implements DemoMode, return ptsF; } + protected int getBoltPointsArrayResource() { + return R.array.batterymeter_bolt_points; + } + private void drawCircle(Canvas canvas, BatteryTracker tracker, float textX, RectF drawRect) { boolean unknownStatus = tracker.status == BatteryManager.BATTERY_STATUS_UNKNOWN; diff --git a/packages/SystemUI/src/com/android/systemui/DockBatteryLevelTextView.java b/packages/SystemUI/src/com/android/systemui/DockBatteryLevelTextView.java new file mode 100644 index 0000000..1678e94 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/DockBatteryLevelTextView.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2015 The CyanogenMod 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; + +import android.content.Context; +import android.graphics.Paint; +import android.util.AttributeSet; + +public class DockBatteryLevelTextView extends BatteryLevelTextView { + + public DockBatteryLevelTextView(Context context, AttributeSet attrs) { + super(context, attrs); + setPaintFlags(getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); + } + +} diff --git a/packages/SystemUI/src/com/android/systemui/DockBatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/DockBatteryMeterView.java new file mode 100755 index 0000000..b80e6d0 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/DockBatteryMeterView.java @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2016 The CyanogenMod 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; + +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.os.BatteryManager; +import android.util.AttributeSet; +import android.view.View; + +public class DockBatteryMeterView extends BatteryMeterView { + + private BatteryManager mBatteryService; + private final boolean mSupported; + + private class DockBatteryTracker extends BatteryTracker { + + public DockBatteryTracker() { + super(); + present = false; + } + + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { + if (testmode && ! intent.getBooleanExtra("testmode", false)) return; + + if (mSupported) { + level = (int)(100f + * intent.getIntExtra(BatteryManager.EXTRA_DOCK_LEVEL, 0) + / intent.getIntExtra(BatteryManager.EXTRA_DOCK_SCALE, 100)); + + present = intent.getBooleanExtra(BatteryManager.EXTRA_DOCK_PRESENT, false); + plugType = intent.getIntExtra(BatteryManager.EXTRA_DOCK_PLUGGED, 0); + // We need to add a extra check over the status because of dock batteries + // PlugType doesn't means that the dock battery is charging (some devices + // doesn't charge under dock usb) + plugged = plugType != 0 && (status == BatteryManager.BATTERY_STATUS_CHARGING || + status == BatteryManager.BATTERY_STATUS_FULL); + health = intent.getIntExtra(BatteryManager.EXTRA_DOCK_HEALTH, + BatteryManager.BATTERY_HEALTH_UNKNOWN); + status = intent.getIntExtra(BatteryManager.EXTRA_DOCK_STATUS, + BatteryManager.BATTERY_STATUS_UNKNOWN); + technology = intent.getStringExtra(BatteryManager.EXTRA_DOCK_TECHNOLOGY); + voltage = intent.getIntExtra(BatteryManager.EXTRA_DOCK_VOLTAGE, 0); + temperature = intent.getIntExtra(BatteryManager.EXTRA_DOCK_TEMPERATURE, 0); + + + if (present && (mMeterMode != BatteryMeterMode.BATTERY_METER_GONE && + mMeterMode != BatteryMeterMode.BATTERY_METER_TEXT)) { + setContentDescription(context.getString( + R.string.accessibility_dock_battery_level, level)); + setVisibility(View.VISIBLE); + invalidate(); + } else { + setContentDescription(null); + setVisibility(View.GONE); + } + } else { + setContentDescription(null); + setVisibility(View.GONE); + + // If dock is not supported then we don't need this receiver anymore + getContext().unregisterReceiver(this); + } + } else if (action.equals(ACTION_LEVEL_TEST)) { + testmode = true; + post(new Runnable() { + int curLevel = 0; + int incr = 1; + int saveLevel = level; + int savePlugged = plugType; + Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED); + @Override + public void run() { + if (curLevel < 0) { + testmode = false; + dummy.putExtra("level", saveLevel); + dummy.putExtra("plugged", savePlugged); + dummy.putExtra("testmode", false); + } else { + dummy.putExtra("level", curLevel); + dummy.putExtra("plugged", incr > 0 + ? BatteryManager.BATTERY_DOCK_PLUGGED_AC : 0); + dummy.putExtra("testmode", true); + } + getContext().sendBroadcast(dummy); + + if (!testmode) return; + + curLevel += incr; + if (curLevel == 100) { + incr *= -1; + } + postDelayed(this, 200); + } + }); + } + } + } + + public DockBatteryMeterView(Context context) { + this(context, null, 0); + } + + public DockBatteryMeterView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public DockBatteryMeterView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + mBatteryService = ((BatteryManager) context.getSystemService(Context.BATTERY_SERVICE)); + mSupported = mBatteryService.isDockBatterySupported(); + mDemoTracker = new DockBatteryTracker(); + mTracker = new DockBatteryTracker(); + } + + @Override + public void onDetachedFromWindow() { + // We already unregistered the listener once when we decided + // support was absent. Don't do it again. + if (mSupported) { + super.onDetachedFromWindow(); + } + } + + @Override + public void setMode(BatteryMeterMode mode) { + super.setMode(mode); + int visibility = getVisibility(); + if (visibility == View.VISIBLE && !mSupported) { + setVisibility(View.GONE); + } + } + + @Override + protected BatteryMeterDrawable createBatteryMeterDrawable(BatteryMeterMode mode) { + Resources res = mContext.getResources(); + switch (mode) { + case BATTERY_METER_CIRCLE: + return new DockCircleBatteryMeterDrawable(res); + case BATTERY_METER_ICON_LANDSCAPE: + return new DockNormalBatteryMeterDrawable(res, true); + case BATTERY_METER_TEXT: + case BATTERY_METER_GONE: + return null; + default: + return new DockNormalBatteryMeterDrawable(res, false); + } + } + + protected class DockNormalBatteryMeterDrawable extends NormalBatteryMeterDrawable { + + public DockNormalBatteryMeterDrawable(Resources res, boolean horizontal) { + super(res, horizontal); + } + + @Override + protected int getBoltPointsArrayResource() { + return mHorizontal + ? R.array.dockbatterymeter_inverted_bolt_points + : R.array.dockbatterymeter_bolt_points; + } + } + + protected class DockCircleBatteryMeterDrawable extends CircleBatteryMeterDrawable { + public DockCircleBatteryMeterDrawable(Resources res) { + super(res); + } + + @Override + protected int getBoltPointsArrayResource() { + return R.array.dockbatterymeter_bolt_points; + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 17fadbd..06ce8cc 100755 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -151,6 +151,8 @@ public class KeyguardViewMediator extends SystemUI { "com.android.internal.action.KEYGUARD_SERVICE_STATE_CHANGED"; private static final String KEYGUARD_SERVICE_EXTRA_ACTIVE = "active"; + private static final String DECRYPT_STATE = "trigger_restart_framework"; + // used for handler messages private static final int SHOW = 2; private static final int HIDE = 3; @@ -203,7 +205,6 @@ public class KeyguardViewMediator extends SystemUI { private AudioManager mAudioManager; private StatusBarManager mStatusBarManager; private boolean mSwitchingUser; - private ProfileManager mProfileManager; private boolean mSystemReady; private boolean mBootCompleted; private boolean mBootSendUserPresent; @@ -290,7 +291,7 @@ public class KeyguardViewMediator extends SystemUI { /** * Whether we are disabling the lock screen internally */ - private Boolean mInternallyDisabled = null; + private boolean mInternallyDisabled = false; /** * we send this intent when the keyguard is dismissed. @@ -344,6 +345,8 @@ public class KeyguardViewMediator extends SystemUI { */ private boolean mPendingLock; + private boolean mCryptKeeperEnabled = true; + private boolean mWakeAndUnlocking; private IKeyguardDrawnCallback mDrawnCallback; @@ -517,7 +520,10 @@ public class KeyguardViewMediator extends SystemUI { break; case READY: synchronized (this) { - if (mShowing) { + if ((mInternallyDisabled || isProfileDisablingKeyguard()) + && !mUpdateMonitor.isSimPinSecure()) { + hideLocked(); + } else if (mShowing) { resetStateLocked(); } } @@ -625,12 +631,12 @@ public class KeyguardViewMediator extends SystemUI { mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard"); mShowKeyguardWakeLock.setReferenceCounted(false); - mProfileManager = ProfileManager.getInstance(mContext); mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION)); mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DISMISS_KEYGUARD_SECURELY_ACTION), android.Manifest.permission.CONTROL_KEYGUARD, null); mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(KEYGUARD_SERVICE_ACTION_STATE_CHANGE), android.Manifest.permission.CONTROL_KEYGUARD, null); + mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(TelephonyManager.ACTION_PHONE_STATE_CHANGED)); mKeyguardDisplayManager = new KeyguardDisplayManager(mContext); @@ -691,18 +697,12 @@ public class KeyguardViewMediator extends SystemUI { getPersistedDefaultOldSetting() ? 1 : 0, UserHandle.USER_CURRENT) == 0; - if (mKeyguardBound) { - if (mInternallyDisabled == null) { - // if it's enabled on boot, don't go through the notions of - // setting it enabled, as it might cause a flicker, just set the state - if (newDisabledState) { - setKeyguardEnabledInternal(false); // will set mInternallyDisabled - } else { - mInternallyDisabled = false; + synchronized (KeyguardViewMediator.this) { + if (mKeyguardBound) { + if (newDisabledState != mInternallyDisabled) { + // it was updated, + setKeyguardEnabledInternal(!newDisabledState); } - } else if (newDisabledState != mInternallyDisabled) { - // it was updated, - setKeyguardEnabledInternal(!newDisabledState); } } } @@ -761,7 +761,7 @@ public class KeyguardViewMediator extends SystemUI { Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e); } mExitSecureCallback = null; - if (!mExternallyEnabled) { + if (!mInternallyDisabled && !mExternallyEnabled) { hideLocked(); } } else if (mShowing) { @@ -914,15 +914,27 @@ public class KeyguardViewMediator extends SystemUI { if (DEBUG) Log.d(TAG, "isKeyguardDisabled: keyguard is disabled by setting"); return true; } - Profile profile = mProfileManager.getActiveProfile(); - if (profile != null) { - if (profile.getScreenLockMode().getValue() == Profile.LockMode.DISABLE) { - if (DEBUG) Log.d(TAG, "isKeyguardDisabled: keyguard is disabled by profile"); - return true; - } - } + if (mInternallyDisabled) { + if (DEBUG) Log.d(TAG, "isKeyguardDisabled: keyguard is disabled internally"); + return true; + } + if (isProfileDisablingKeyguard()) { + if (DEBUG) Log.d(TAG, "isKeyguardDisabled: keyguard is disabled by profile"); + return true; + } return false; - } + } + + private boolean isCryptKeeperEnabled() { + if (!mCryptKeeperEnabled) { + // once it's disabled, it's disabled. + return false; + } + final String state = SystemProperties.get("vold.decrypt"); + mCryptKeeperEnabled = !"".equals(state) && !DECRYPT_STATE.equals(state); + if (DEBUG) Log.w(TAG, "updated crypt keeper state to: " + mCryptKeeperEnabled); + return mCryptKeeperEnabled; + } /** * A dream started. We should lock after the usual screen-off lock timeout but only @@ -955,6 +967,10 @@ public class KeyguardViewMediator extends SystemUI { */ public void setKeyguardEnabledInternal(boolean enabled) { mInternallyDisabled = !enabled; + if (!mUpdateMonitor.isSimPinSecure()) { + // disable when sim is ready + return; + } setKeyguardEnabled(enabled); if (mInternallyDisabled) { mNeedToReshowWhenReenabled = false; @@ -965,6 +981,12 @@ public class KeyguardViewMediator extends SystemUI { return !mInternallyDisabled; } + public boolean isProfileDisablingKeyguard() { + final Profile activeProfile = ProfileManager.getInstance(mContext).getActiveProfile(); + return activeProfile != null + && activeProfile.getScreenLockMode().getValue() == Profile.LockMode.DISABLE; + } + /** * Same semantics as {@link android.view.WindowManagerPolicy#enableKeyguard}; provide * a way for external stuff to override normal keyguard behavior. For instance @@ -973,15 +995,15 @@ public class KeyguardViewMediator extends SystemUI { public void setKeyguardEnabled(boolean enabled) { synchronized (this) { if (DEBUG) Log.d(TAG, "setKeyguardEnabled(" + enabled + ")"); - - if (mInternallyDisabled && enabled && !lockscreenEnforcedByDevicePolicy()) { + mExternallyEnabled = enabled; + if (mInternallyDisabled + && enabled + && !lockscreenEnforcedByDevicePolicy()) { // if keyguard is forcefully disabled internally (by lock screen tile), don't allow // it to be enabled externally, unless the device policy manager says so. return; } - mExternallyEnabled = enabled; - if (!enabled && mShowing) { if (mExitSecureCallback != null) { if (DEBUG) Log.d(TAG, "in process of verifyUnlock request, ignoring"); @@ -993,7 +1015,7 @@ public class KeyguardViewMediator extends SystemUI { // hiding keyguard that is showing, remember to reshow later if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, " + "disabling status bar expansion"); - mNeedToReshowWhenReenabled = true; + mNeedToReshowWhenReenabled = !isProfileDisablingKeyguard(); updateInputRestrictedLocked(); hideLocked(); } else if (enabled && mNeedToReshowWhenReenabled) { @@ -1173,22 +1195,6 @@ public class KeyguardViewMediator extends SystemUI { * Enable the keyguard if the settings are appropriate. */ private void doKeyguardLocked(Bundle options) { - // if another app is disabling us, don't show - if (!mExternallyEnabled) { - if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled"); - - // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes - // for an occasional ugly flicker in this situation: - // 1) receive a call with the screen on (no keyguard) or make a call - // 2) screen times out - // 3) user hits key to turn screen back on - // instead, we reenable the keyguard when we know the screen is off and the call - // ends (see the broadcast receiver below) - // TODO: clean this up when we have better support at the window manager level - // for apps that wish to be on top of the keyguard - return; - } - // if the keyguard is already showing, don't bother if (mStatusBarKeyguardViewManager.isShowing()) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing"); @@ -1196,6 +1202,14 @@ public class KeyguardViewMediator extends SystemUI { return; } + // Ugly hack to ensure keyguard is not shown on top of the CryptKeeper which prevents + // a user from being able to decrypt their device. + if (isCryptKeeperEnabled()) { + if (DEBUG) Log.d(TAG, "doKeyguard: not showing because CryptKeeper is enabled"); + resetStateLocked(); + return; + } + // if the setup wizard hasn't run yet, don't show final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim", false); final boolean absent = SubscriptionManager.isValidSubscriptionId( @@ -1211,9 +1225,30 @@ public class KeyguardViewMediator extends SystemUI { return; } + // if another app is disabling us, don't show + if (!mExternallyEnabled && !lockedOrMissing) { + if (DEBUG) Log.d(TAG, "doKeyguard: not showing because externally disabled"); + + // note: we *should* set mNeedToReshowWhenReenabled=true here, but that makes + // for an occasional ugly flicker in this situation: + // 1) receive a call with the screen on (no keyguard) or make a call + // 2) screen times out + // 3) user hits key to turn screen back on + // instead, we reenable the keyguard when we know the screen is off and the call + // ends (see the broadcast receiver below) + // TODO: clean this up when we have better support at the window manager level + // for apps that wish to be on top of the keyguard + return; + } + if (isKeyguardDisabled(KeyguardUpdateMonitor.getCurrentUser()) && !lockedOrMissing) { if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off"); + // update state + setShowingLocked(false); + updateActivityLockScreenState(); + adjustStatusBarLocked(); + userActivity(); return; } @@ -1238,15 +1273,7 @@ public class KeyguardViewMediator extends SystemUI { DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); if (dpm != null) { - int passwordQuality = dpm.getPasswordQuality(null); - switch (passwordQuality) { - case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC: - case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC: - case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX: - case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC: - case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING: - return true; - } + return dpm.requireSecureKeyguard(); } return false; } @@ -1376,6 +1403,9 @@ public class KeyguardViewMediator extends SystemUI { } else { mSettingsObserver.unobserve(); } + } else if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(intent.getAction())) { + mPhoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE); + if (DEBUG) Log.d(TAG, "phone state change, new state: " + mPhoneState); } } }; @@ -1541,6 +1571,10 @@ public class KeyguardViewMediator extends SystemUI { private void playSound(int soundId) { if (soundId == 0) return; + if (mInternallyDisabled) { + Log.d(TAG, "suppressing lock screen sounds because it is disabled"); + return; + } final ContentResolver cr = mContext.getContentResolver(); if (Settings.System.getInt(cr, Settings.System.LOCKSCREEN_SOUNDS_ENABLED, 1) == 1) { @@ -1726,7 +1760,7 @@ public class KeyguardViewMediator extends SystemUI { private void handleReset() { synchronized (KeyguardViewMediator.this) { if (DEBUG) Log.d(TAG, "handleReset"); - mStatusBarKeyguardViewManager.reset(); + mStatusBarKeyguardViewManager.reset(false); } } diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java index a1a11ca..e519e34 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java @@ -237,8 +237,8 @@ public class PowerUI extends SystemUI { if (mIgnoreFirstPowerEvent) { mIgnoreFirstPowerEvent = false; } else { - if (CMSettings.Global.getInt(cr, - CMSettings.Global.POWER_NOTIFICATIONS_ENABLED, 0) == 1) { + if (Settings.Global.getInt(cr, + Settings.Global.CHARGING_SOUNDS_ENABLED, 0) == 1) { playPowerNotificationSound(); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSBooleanSettingRow.java b/packages/SystemUI/src/com/android/systemui/qs/QSBooleanSettingRow.java index d2d13ae..50845da 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSBooleanSettingRow.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSBooleanSettingRow.java @@ -49,6 +49,7 @@ public class QSBooleanSettingRow extends LinearLayout implements View.OnClickLis private TextView mText; private Switch mSwitch; private int mDefaultValue; + private CompoundButton.OnCheckedChangeListener mOnCheckedChangeListener; public QSBooleanSettingRow(Context context) { this(context, null); @@ -99,6 +100,9 @@ public class QSBooleanSettingRow extends LinearLayout implements View.OnClickLis + "buttonView = [" + buttonView + "], isChecked = [" + isChecked + "] and table: " + mWhichTable + ", and key: " + mKey); applyChange(isChecked); + if (mOnCheckedChangeListener != null) { + mOnCheckedChangeListener.onCheckedChanged(buttonView, isChecked); + } } }); } @@ -106,6 +110,13 @@ public class QSBooleanSettingRow extends LinearLayout implements View.OnClickLis a.recycle(); } + public void setChecked(boolean checked) { + if (mSwitch.isChecked() == checked) { + return; + } + mSwitch.setChecked(checked); + } + private void applyChange(boolean value) { ContentResolver cr = getContext().getContentResolver(); switch (mWhichTable) { @@ -160,4 +171,8 @@ public class QSBooleanSettingRow extends LinearLayout implements View.OnClickLis public void onClick(View v) { mSwitch.setChecked(!mSwitch.isChecked()); } + + public void setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener l) { + mOnCheckedChangeListener = l; + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java index 0615842..86fc49e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSDragPanel.java @@ -89,6 +89,9 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On private static final int MAX_ROW_COUNT = 3; + // how long to wait before resetting the page + private static final int PAGE_RESET_DELAY = 10000; + protected final ArrayList<QSPage> mPages = new ArrayList<>(); protected QSViewPager mViewPager; @@ -119,6 +122,16 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On private Point mDisplaySize; private int[] mTmpLoc; + private Runnable mResetPage = new Runnable() { + @Override + public void run() { + if (!mListening) { + // only reset when the user isn't interacting at all + mViewPager.setCurrentItem(0); + } + } + }; + public QSDragPanel(Context context) { this(context, null); } @@ -369,6 +382,12 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On public void setListening(boolean listening) { if (mListening == listening) return; mListening = listening; + // reset the page when inactive for a while + if (listening) { + removeCallbacks(mResetPage); + } else { + postDelayed(mResetPage, PAGE_RESET_DELAY); + } for (TileRecord r : mRecords) { r.tile.setListening(mListening); } @@ -481,36 +500,6 @@ public class QSDragPanel extends QSPanel implements View.OnDragListener, View.On mDetailRemoveButton.setText(R.string.quick_settings_remove); } - /** - * @return returns the number of pages that has at least 1 visible tile - */ - protected int getVisibleTilePageCount() { - // if all tiles are invisible on the page, do not count it - int pages = 0; - - int lastPage = -1; - boolean allTilesInvisible = true; - - for (TileRecord record : mRecords) { - DragTileRecord dr = (DragTileRecord) record; - if (dr.destinationPage != lastPage) { - if (!allTilesInvisible) { - pages++; - } - lastPage = dr.destinationPage; - allTilesInvisible = true; - } - if (allTilesInvisible && dr.tile.getState().visible) { - allTilesInvisible = false; - } - } - // last tile may have set this - if (!allTilesInvisible) { - pages++; - } - return pages; - } - public void setTiles(final Collection<QSTile<?>> tilesCollection) { final List<QSTile<?>> tiles = new ArrayList<>(tilesCollection); if (DEBUG_TILES) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSettings.java b/packages/SystemUI/src/com/android/systemui/qs/QSSettings.java index 7766ca4..0a2b937 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSettings.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSettings.java @@ -15,15 +15,22 @@ */ package com.android.systemui.qs; +import android.Manifest; import android.annotation.Nullable; +import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.os.Handler; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.ResultReceiver; import android.util.AttributeSet; -import android.util.Log; -import android.view.MotionEvent; import android.view.View; -import android.widget.LinearLayout; +import android.widget.CompoundButton; import android.widget.ScrollView; import com.android.systemui.R; @@ -32,9 +39,16 @@ import com.android.systemui.statusbar.phone.SystemUIDialog; public class QSSettings extends ScrollView { + private static final String RESULT_RECEIVER_EXTRA = "result_receiver"; + private static final String LOCK_CLOCK_PACKAGENAME = "com.cyanogenmod.lockclock"; + private static final String LOCK_CLOCK_PERM_CLASS = LOCK_CLOCK_PACKAGENAME + + ".weather.PermissionRequestActivity"; + private QSTileHost mHost; private boolean mAdapterEditingState; + private QSBooleanSettingRow mShowWeather; + private ResultReceiver mResultReceiver; public QSSettings(Context context, @Nullable AttributeSet attrs) { super(context, attrs); @@ -51,6 +65,51 @@ public class QSSettings extends ScrollView { initiateTileReset(); } }); + + mShowWeather = (QSBooleanSettingRow) findViewById(R.id.show_weather); + mShowWeather.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (isChecked) { + PackageManager packageManager = getContext().getPackageManager(); + if (packageManager.checkPermission(Manifest.permission.ACCESS_COARSE_LOCATION, + LOCK_CLOCK_PACKAGENAME) != PackageManager.PERMISSION_GRANTED) { + mShowWeather.setChecked(false); + requestPermission(); + mHost.collapsePanels(); + } + } + } + }); + } + + public Parcelable getResultReceiverForSending() { + if (mResultReceiver == null) { + mResultReceiver = new ResultReceiver(new Handler()) { + @Override + protected void onReceiveResult(int resultCode, Bundle resultData) { + super.onReceiveResult(resultCode, resultData); + if (resultCode == Activity.RESULT_OK) { + mShowWeather.setChecked(true); + } + mResultReceiver = null; + } + }; + } + Parcel parcel = Parcel.obtain(); + mResultReceiver.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel); + parcel.recycle(); + return receiverForSending; + } + + private void requestPermission() { + Intent i = new Intent(); + i.setClassName(LOCK_CLOCK_PACKAGENAME, LOCK_CLOCK_PERM_CLASS); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + i.putExtra(RESULT_RECEIVER_EXTRA, getResultReceiverForSending()); + getContext().startActivity(i); } private void initiateTileReset() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CaffeineTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CaffeineTile.java new file mode 100644 index 0000000..fb6ec42 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CaffeineTile.java @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2016 The CyanogenMod 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.qs.tiles; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.CountDownTimer; +import android.os.PowerManager; +import android.os.SystemClock; +import android.provider.Settings; + +import com.android.systemui.qs.QSTile; +import com.android.systemui.R; + +import org.cyanogenmod.internal.logging.CMMetricsLogger; + +/** Quick settings tile: Caffeine **/ +public class CaffeineTile extends QSTile<QSTile.BooleanState> { + + private final PowerManager.WakeLock mWakeLock; + private int mSecondsRemaining; + private int mDuration; + private static int[] DURATIONS = new int[] { + 5 * 60, // 5 min + 10 * 60, // 10 min + 30 * 60, // 30 min + -1, // infinity + }; + private CountDownTimer mCountdownTimer = null; + public long mLastClickTime = -1; + private final Receiver mReceiver = new Receiver(); + private boolean mListening; + + public CaffeineTile(Host host) { + super(host); + mWakeLock = ((PowerManager) mContext.getSystemService(Context.POWER_SERVICE)).newWakeLock( + PowerManager.FULL_WAKE_LOCK, "CaffeineTile"); + mReceiver.init(); + } + + @Override + protected BooleanState newTileState() { + return new BooleanState(); + } + + @Override + protected void handleDestroy() { + super.handleDestroy(); + stopCountDown(); + mReceiver.destroy(); + if (mWakeLock.isHeld()) { + mWakeLock.release(); + } + } + + @Override + public void setListening(boolean listening) { + } + + @Override + public void handleClick() { + // If last user clicks < 5 seconds + // we cycle different duration + // otherwise toggle on/off + if (mWakeLock.isHeld() && (mLastClickTime != -1) && + (SystemClock.elapsedRealtime() - mLastClickTime < 5000)) { + // cycle duration + mDuration++; + if (mDuration >= DURATIONS.length) { + // all durations cycled, turn if off + mDuration = -1; + stopCountDown(); + if (mWakeLock.isHeld()) { + mWakeLock.release(); + } + } else { + // change duration + startCountDown(DURATIONS[mDuration]); + if (!mWakeLock.isHeld()) { + mWakeLock.acquire(); + } + } + } else { + // toggle + if (mWakeLock.isHeld()) { + mWakeLock.release(); + stopCountDown(); + } else { + mWakeLock.acquire(); + mDuration = 0; + startCountDown(DURATIONS[mDuration]); + } + } + mLastClickTime = SystemClock.elapsedRealtime(); + refreshState(); + } + + private void startCountDown(long duration) { + stopCountDown(); + mSecondsRemaining = (int)duration; + if (duration == -1) { + // infinity timing, no need to start timer + return; + } + mCountdownTimer = new CountDownTimer(duration * 1000, 1000) { + + @Override + public void onTick(long millisUntilFinished) { + mSecondsRemaining = (int) (millisUntilFinished / 1000); + refreshState(); + } + + @Override + public void onFinish() { + if (mWakeLock.isHeld()) + mWakeLock.release(); + refreshState(); + } + + }.start(); + } + + private void stopCountDown() { + if (mCountdownTimer != null) { + mCountdownTimer.cancel(); + mCountdownTimer = null; + } + } + + private String formatValueWithRemainingTime() { + if (mSecondsRemaining == -1) { + return "\u221E"; // infinity + } + return String.format("%02d:%02d", + mSecondsRemaining / 60 % 60, mSecondsRemaining % 60); + } + + @Override + protected void handleUpdateState(BooleanState state, Object arg) { + state.value = mWakeLock.isHeld(); + state.visible = true; + if (state.value) { + state.label = formatValueWithRemainingTime(); + state.icon = ResourceIcon.get(R.drawable.ic_qs_caffeine_on); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_caffeine_on); + } else { + state.label = mContext.getString(R.string.quick_settings_caffeine_label); + state.icon = ResourceIcon.get(R.drawable.ic_qs_caffeine_off); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_caffeine_off); + } + } + + @Override + public int getMetricsCategory() { + return CMMetricsLogger.TILE_CAFFEINE; + } + + private final class Receiver extends BroadcastReceiver { + public void init() { + // Register for Intent broadcasts for... + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_SCREEN_OFF); + mContext.registerReceiver(this, filter, null, mHandler); + } + + public void destroy() { + mContext.unregisterReceiver(this); + } + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (Intent.ACTION_SCREEN_OFF.equals(action)) { + // disable caffeine if user force off (power button) + stopCountDown(); + if (mWakeLock.isHeld()) + mWakeLock.release(); + refreshState(); + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index f83bbf4..cd608d6 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -208,12 +208,14 @@ public class CastTile extends QSTile<QSTile.BooleanState> { @Override public void onViewAttachedToWindow(View v) { if (DEBUG) Log.d(TAG, "onViewAttachedToWindow"); + mController.setDiscovering(true); } @Override public void onViewDetachedFromWindow(View v) { if (DEBUG) Log.d(TAG, "onViewDetachedFromWindow"); mVisibleOrder.clear(); + mController.setDiscovering(false); } }); } @@ -221,7 +223,6 @@ public class CastTile extends QSTile<QSTile.BooleanState> { R.string.quick_settings_cast_detail_empty_text); mItems.setCallback(this); updateItems(mController.getCastDevices()); - mController.setDiscovering(true); return mItems; } 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 f4602de..038fa5e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java @@ -17,10 +17,12 @@ package com.android.systemui.qs.tiles; +import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.os.UserHandle; import android.telephony.TelephonyManager; import android.view.LayoutInflater; import android.view.View; @@ -47,11 +49,8 @@ public class CellularTile extends QSTile<QSTile.SignalState> { private static final Intent MOBILE_NETWORK_SETTINGS = new Intent(Intent.ACTION_MAIN) .setComponent(new ComponentName("com.android.phone", "com.android.phone.MobileNetworkSettings")); - private static final Intent MOBILE_NETWORK_SETTINGS_MSIM = new Intent(Intent.ACTION_MAIN) - .setClassName("com.android.phone", "com.android.phone.msim.SelectSubscription") - .putExtra("PACKAGE", "com.android.phone") - .putExtra("TARGET_CLASS", "com.android.phone.MobileNetworkSettings") - .putExtra("TARGET_THEME", "Theme.Material.Settings"); + private static final Intent MOBILE_NETWORK_SETTINGS_MSIM + = new Intent("com.android.settings.sim.SIM_SUB_INFO_SETTINGS"); private final NetworkController mController; private final MobileDataController mDataController; @@ -93,6 +92,13 @@ public class CellularTile extends QSTile<QSTile.SignalState> { } @Override + protected void handleUserSwitch(int newUserId) { + if (newUserId != UserHandle.USER_OWNER) { + refreshState(); + } + } + + @Override protected void handleClick() { MetricsLogger.action(mContext, getMetricsCategory()); if (mDataController.isMobileDataSupported()) { @@ -118,7 +124,8 @@ public class CellularTile extends QSTile<QSTile.SignalState> { @Override protected void handleUpdateState(SignalState state, Object arg) { - state.visible = mController.hasMobileDataFeature(); + state.visible = mController.hasMobileDataFeature() + && (ActivityManager.getCurrentUser() == UserHandle.USER_OWNER); if (!state.visible) return; CallbackInfo cb = (CallbackInfo) arg; if (cb == null) { @@ -140,7 +147,9 @@ public class CellularTile extends QSTile<QSTile.SignalState> { state.label = cb.enabled ? removeTrailingPeriod(cb.enabledDesc) - : r.getString(R.string.quick_settings_rssi_emergency_only); + : mDataController.isMobileDataSupported() ? + r.getString(R.string.data_sim_not_configured) : + r.getString(R.string.quick_settings_rssi_emergency_only); final String signalContentDesc = cb.enabled && (cb.mobileSignalIconId > 0) ? cb.signalContentDescription @@ -225,10 +234,14 @@ public class CellularTile extends QSTile<QSTile.SignalState> { // Make sure signal gets cleared out when no sims. mInfo.mobileSignalIconId = 0; mInfo.dataTypeIconId = 0; - // Show a No SIMs description to avoid emergency calls message. + // Show a No SIMs description if we're incapable of supporting mobile data + // to avoid showing an emergency mode description. If we're still capable of + // supporting mobile data, notify the user that the data sim is not configured + // only relevant in MSIM scenario: CYNGNOS-2211 mInfo.enabled = true; - mInfo.enabledDesc = mContext.getString( - R.string.keyguard_missing_sim_message_short); + mInfo.enabledDesc = mDataController.isMobileDataSupported() ? + mContext.getString(R.string.data_sim_not_configured) + : mContext.getString(R.string.keyguard_missing_sim_message_short); mInfo.signalContentDescription = mInfo.enabledDesc; } refreshState(mInfo); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index 0cb9dcf..0d43f8c 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -114,7 +114,7 @@ public class DndTile extends QSTile<QSTile.BooleanState> { mDisableTotalSilence.setAllowAnimation(true); MetricsLogger.action(mContext, getMetricsCategory(), !mState.value); if (mState.value) { - showDetail(true); + mController.setZen(Global.ZEN_MODE_OFF, null, TAG); } else { int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS); mController.setZen(zen, null, TAG); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index d1b167e..25a7fb7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -21,6 +21,9 @@ import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.wifi.WifiDevice; import android.provider.Settings; import com.android.internal.logging.MetricsLogger; @@ -31,6 +34,8 @@ import com.android.systemui.qs.UsageTracker; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.HotspotController; +import java.util.List; + /** Quick settings tile: Hotspot **/ public class HotspotTile extends QSTile<QSTile.BooleanState> { @@ -44,12 +49,16 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> { private final HotspotController mController; private final Callback mCallback = new Callback(); private final UsageTracker mUsageTracker; + private final ConnectivityManager mConnectivityManager; + private boolean mListening; + private int mNumConnectedClients = 0; public HotspotTile(Host host) { super(host); mController = host.getHotspotController(); mUsageTracker = newUsageTracker(host.getContext()); mUsageTracker.setListening(true); + mConnectivityManager = host.getContext().getSystemService(ConnectivityManager.class); } @Override @@ -65,11 +74,16 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> { @Override public void setListening(boolean listening) { + if (mListening == listening) return; if (listening) { mController.addCallback(mCallback); + mContext.registerReceiver(mTetherConnectStateChangedReceiver, + new IntentFilter(ConnectivityManager.TETHER_CONNECT_STATE_CHANGED)); } else { mController.removeCallback(mCallback); + mContext.unregisterReceiver(mTetherConnectStateChangedReceiver); } + mListening = listening; } @Override @@ -111,13 +125,19 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> { @Override protected void handleUpdateState(BooleanState state, Object arg) { state.visible = mController.isHotspotSupported() && mUsageTracker.isRecentlyUsed(); - state.label = mContext.getString(R.string.quick_settings_hotspot_label); if (arg instanceof Boolean) { state.value = (boolean) arg; } else { state.value = mController.isHotspotEnabled(); } + if (state.visible && state.value) { + state.label = mContext.getResources().getQuantityString( + R.plurals.wifi_hotspot_connected_clients_label, mNumConnectedClients, + mNumConnectedClients); + } else { + state.label = mContext.getString(R.string.quick_settings_hotspot_label); + } state.icon = state.visible && state.value ? mEnable : mDisable; } @@ -140,6 +160,15 @@ public class HotspotTile extends QSTile<QSTile.BooleanState> { R.integer.days_to_show_hotspot_tile); } + private BroadcastReceiver mTetherConnectStateChangedReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final List<WifiDevice> clients = mConnectivityManager.getTetherConnectedSta(); + mNumConnectedClients = clients != null ? clients.size() : 0; + refreshState(); + } + }; + private final class Callback implements HotspotController.Callback { @Override public void onHotspotChanged(boolean enabled) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LiveDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LiveDisplayTile.java index b14934f..f59c876 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LiveDisplayTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LiveDisplayTile.java @@ -16,14 +16,12 @@ package com.android.systemui.qs.tiles; -import android.content.Context; import android.content.Intent; import android.content.res.Resources; import android.content.res.TypedArray; import android.database.ContentObserver; import android.os.Handler; import android.os.UserHandle; -import android.provider.Settings; import com.android.internal.util.ArrayUtils; import com.android.systemui.R; @@ -40,10 +38,10 @@ public class LiveDisplayTile extends QSTile<LiveDisplayTile.LiveDisplayState> { new Intent("android.settings.LIVEDISPLAY_SETTINGS"); private final LiveDisplayObserver mObserver; - private final String[] mEntries; - private final String[] mDescriptionEntries; - private final String[] mAnnouncementEntries; - private final String[] mValues; + private String[] mEntries; + private String[] mDescriptionEntries; + private String[] mAnnouncementEntries; + private String[] mValues; private final int[] mEntryIconRes; private boolean mListening; @@ -69,10 +67,7 @@ public class LiveDisplayTile extends QSTile<LiveDisplayTile.LiveDisplayState> { } typedArray.recycle(); - mEntries = res.getStringArray(com.android.internal.R.array.live_display_entries); - mDescriptionEntries = res.getStringArray(R.array.live_display_description); - mAnnouncementEntries = res.getStringArray(R.array.live_display_announcement); - mValues = res.getStringArray(com.android.internal.R.array.live_display_values); + updateEntries(); mOutdoorModeAvailable = CMHardwareManager.getInstance(mContext) @@ -86,6 +81,14 @@ public class LiveDisplayTile extends QSTile<LiveDisplayTile.LiveDisplayState> { mObserver.startObserving(); } + private void updateEntries() { + Resources res = mContext.getResources(); + mEntries = res.getStringArray(com.android.internal.R.array.live_display_entries); + mDescriptionEntries = res.getStringArray(R.array.live_display_description); + mAnnouncementEntries = res.getStringArray(R.array.live_display_announcement); + mValues = res.getStringArray(com.android.internal.R.array.live_display_values); + } + @Override protected LiveDisplayState newTileState() { return new LiveDisplayState(); @@ -115,6 +118,7 @@ public class LiveDisplayTile extends QSTile<LiveDisplayTile.LiveDisplayState> { @Override protected void handleUpdateState(LiveDisplayState state, Object arg) { + updateEntries(); state.visible = true; state.mode = arg == null ? getCurrentModeIndex() : (Integer) arg; state.label = mEntries[state.mode]; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java index 2d764ba..a147d30 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LockscreenToggleTile.java @@ -23,6 +23,9 @@ import com.android.systemui.SystemUIApplication; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.qs.QSTile; import com.android.systemui.statusbar.policy.KeyguardMonitor; + +import cyanogenmod.app.Profile; +import cyanogenmod.app.ProfileManager; import cyanogenmod.providers.CMSettings; import org.cyanogenmod.internal.logging.CMMetricsLogger; @@ -32,7 +35,6 @@ public class LockscreenToggleTile extends QSTile<QSTile.BooleanState> private static final Intent LOCK_SCREEN_SETTINGS = new Intent("android.settings.LOCK_SCREEN_SETTINGS"); - private KeyguardViewMediator mKeyguardViewMediator; private KeyguardMonitor mKeyguard; private boolean mListening; @@ -42,21 +44,13 @@ public class LockscreenToggleTile extends QSTile<QSTile.BooleanState> super(host); mKeyguard = host.getKeyguardMonitor(); - mKeyguardViewMediator = - ((SystemUIApplication) - mContext.getApplicationContext()).getComponent(KeyguardViewMediator.class); mSettingsObserver = new KeyguardViewMediator.LockscreenEnabledSettingsObserver(mContext, mUiHandler) { @Override public void update() { - boolean newState = CMSettings.Secure.getIntForUser( - mContext.getContentResolver(), - CMSettings.Secure.LOCKSCREEN_INTERNALLY_ENABLED, - getPersistedDefaultOldSetting() ? 1 : 0, - UserHandle.USER_CURRENT) != 0; - refreshState(newState); + refreshState(); } }; @@ -97,24 +91,46 @@ public class LockscreenToggleTile extends QSTile<QSTile.BooleanState> @Override protected void handleUpdateState(BooleanState state, Object arg) { - final boolean lockscreenEnforced = mKeyguardViewMediator.lockscreenEnforcedByDevicePolicy(); - final boolean lockscreenEnabled = lockscreenEnforced || - arg != null ? (Boolean) arg : mKeyguardViewMediator.getKeyguardEnabledInternal(); - - state.value = lockscreenEnabled; - state.visible = mKeyguardViewMediator.isKeyguardBound(); - state.enabled = !mKeyguard.isShowing() || !mKeyguard.isSecure(); - state.label = mContext.getString(lockscreenEnforced - ? R.string.quick_settings_lockscreen_label_enforced - : R.string.quick_settings_lockscreen_label); - if (lockscreenEnabled) { - state.icon = ResourceIcon.get(R.drawable.ic_qs_lock_screen_on); - state.contentDescription = mContext.getString( - R.string.accessibility_quick_settings_lock_screen_on); + KeyguardViewMediator mediator = ((SystemUIApplication) + mContext.getApplicationContext()).getComponent(KeyguardViewMediator.class); + + if (mediator == null) { + state.visible = false; + state.value = false; + state.enabled = false; } else { - state.icon = ResourceIcon.get(R.drawable.ic_qs_lock_screen_off); - state.contentDescription = mContext.getString( - R.string.accessibility_quick_settings_lock_screen_off); + final boolean lockscreenEnforced = mediator.lockscreenEnforcedByDevicePolicy(); + final boolean lockscreenEnabled = lockscreenEnforced || + arg != null ? (Boolean) arg : mediator.getKeyguardEnabledInternal(); + + state.visible = mediator.isKeyguardBound(); + + if (mediator.isProfileDisablingKeyguard()) { + state.value = false; + state.enabled = false; + state.label = mContext.getString( + R.string.quick_settings_lockscreen_label_locked_by_profile); + } else if (lockscreenEnforced) { + state.value = true; + state.enabled = false; + state.label = mContext.getString( + R.string.quick_settings_lockscreen_label_enforced); + } else { + state.value = lockscreenEnabled; + state.enabled = !mKeyguard.isShowing() || !mKeyguard.isSecure(); + + state.label = mContext.getString(R.string.quick_settings_lockscreen_label); + } + // update icon + if (lockscreenEnabled) { + state.icon = ResourceIcon.get(R.drawable.ic_qs_lock_screen_on); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_lock_screen_on); + } else { + state.icon = ResourceIcon.get(R.drawable.ic_qs_lock_screen_off); + state.contentDescription = mContext.getString( + R.string.accessibility_quick_settings_lock_screen_off); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenTimeoutTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenTimeoutTile.java index 81899d3..e933787 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenTimeoutTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenTimeoutTile.java @@ -61,9 +61,6 @@ public class ScreenTimeoutTile extends QSTile<ScreenTimeoutTile.TimeoutState> { new AnimationIcon(R.drawable.ic_qs_screen_timeout_long_reverse_avd); private String[] mEntries, mValues; - private boolean mShowingDetail; - ArrayList<Integer> mAnimationList - = new ArrayList<Integer>(); public ScreenTimeoutTile(Host host) { super(host); @@ -127,8 +124,6 @@ public class ScreenTimeoutTile extends QSTile<ScreenTimeoutTile.TimeoutState> { @Override protected void handleClick() { if (mEntries.length > 0) { - mShowingDetail = true; - mAnimationList.clear(); showDetail(true); } } @@ -190,10 +185,6 @@ public class ScreenTimeoutTile extends QSTile<ScreenTimeoutTile.TimeoutState> { } @Override protected void handleUpdateState(final TimeoutState state, Object arg) { - if (mAnimationList.isEmpty() && mShowingDetail && arg == null) { - return; - } - int newTimeout = getScreenTimeout(); AnimationIcon d = null; @@ -334,7 +325,6 @@ public class ScreenTimeoutTile extends QSTile<ScreenTimeoutTile.TimeoutState> { mUiHandler.postDelayed(new Runnable() { @Override public void run() { - mShowingDetail = false; refreshState(true); } }, 100); diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java index 3917bab..b3a3dfd 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java +++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java @@ -46,6 +46,7 @@ import com.android.systemui.R; import com.android.systemui.RecentsComponent; import com.android.systemui.SystemUI; import com.android.systemui.SystemUIApplication; +import com.android.systemui.cm.UserContentObserver; import com.android.systemui.recents.misc.Console; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.model.RecentsTaskLoadPlan; @@ -61,6 +62,8 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar; import java.util.ArrayList; +import cyanogenmod.providers.CMSettings; + /** * Annotation for a method that is only called from the primary user's SystemUI process and will be * proxied to the current user. @@ -161,6 +164,35 @@ public class Recents extends SystemUI } } + class RecentsSettingsObserver extends UserContentObserver { + + public RecentsSettingsObserver(Handler handler) { + super(handler); + } + + @Override + protected void observe() { + super.observe(); + mContext.getContentResolver().registerContentObserver( + CMSettings.System.getUriFor(CMSettings.System.RECENTS_SHOW_SEARCH_BAR), + false, this); + update(); + } + + @Override + protected void unobserve() { + super.unobserve(); + mContext.getContentResolver().unregisterContentObserver(this); + } + + @Override + protected void update() { + if (mConfig.updateShowSearch(mContext)) { + reloadHeaderBarLayout(); + } + } + } + static RecentsComponent.Callbacks sRecentsComponentCallbacks; static RecentsTaskLoadPlan sInstanceLoadPlan; static Recents sInstance; @@ -171,6 +203,7 @@ public class Recents extends SystemUI TaskStackListenerImpl mTaskStackListener; RecentsOwnerEventProxyReceiver mProxyBroadcastReceiver; RecentsAppWidgetHost mAppWidgetHost; + RecentsSettingsObserver mSettingsObserver; boolean mBootCompleted; boolean mStartAnimationTriggered; boolean mCanReuseTaskStackViews = true; @@ -259,6 +292,9 @@ public class Recents extends SystemUI // Load the header bar layout reloadHeaderBarLayout(); + mSettingsObserver = new RecentsSettingsObserver(mHandler); + mSettingsObserver.observe(); + // When we start, preload the data associated with the previous recent tasks. // We can use a new plan since the caches will be the same. RecentsTaskLoader loader = RecentsTaskLoader.getInstance(); @@ -549,7 +585,8 @@ public class Recents extends SystemUI // Try and pre-emptively bind the search widget on startup to ensure that we // have the right thumbnail bounds to animate to. // Note: We have to reload the widget id before we get the task stack bounds below - if (mSystemServicesProxy.getOrBindSearchAppWidget(mContext, mAppWidgetHost) != null) { + if (mConfig.searchBarEnabled && + mSystemServicesProxy.getOrBindSearchAppWidget(mContext, mAppWidgetHost) != null) { mConfig.getSearchBarBounds(mWindowRect.width(), mWindowRect.height(), mStatusBarHeight, searchBarBounds); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index d1d642f..f4fe677 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -25,11 +25,9 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.res.Resources; import android.os.Bundle; import android.os.SystemClock; import android.os.UserHandle; -import android.provider.Settings; import android.view.KeyEvent; import android.view.View; import android.view.ViewStub; @@ -38,7 +36,6 @@ import android.widget.Toast; import com.android.internal.logging.MetricsLogger; import com.android.systemui.Prefs; import com.android.systemui.R; -import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.misc.Console; import com.android.systemui.recents.misc.DebugTrigger; import com.android.systemui.recents.misc.ReferenceCountedTrigger; @@ -133,7 +130,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView /** * Broadcast receiver to handle messages from AlternateRecentsComponent. */ - private final BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() { + final BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); @@ -163,7 +160,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView /** * Broadcast receiver to handle messages from the system */ - private final BroadcastReceiver mSystemBroadcastReceiver = new BroadcastReceiver() { + final BroadcastReceiver mSystemBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); @@ -182,7 +179,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView /** * A custom debug trigger to listen for a debug key chord. */ - private final DebugTrigger mDebugTrigger = new DebugTrigger(new Runnable() { + final DebugTrigger mDebugTrigger = new DebugTrigger(new Runnable() { @Override public void run() { onDebugModeTriggered(); @@ -211,9 +208,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView ArrayList<TaskStack> stacks = plan.getAllTaskStacks(); mConfig.launchedWithNoRecentTasks = !plan.hasTasks(); - if (!mConfig.launchedWithNoRecentTasks) { - mRecentsView.setTaskStacks(stacks); - } + mRecentsView.setTaskStacks(stacks); // Create the home intent runnable Intent homeIntent = new Intent(Intent.ACTION_MAIN, null); @@ -222,10 +217,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent, ActivityOptions.makeCustomAnimation(this, - mConfig.launchedFromSearchHome ? R.anim.recents_to_search_launcher_enter : - R.anim.recents_to_launcher_enter, - mConfig.launchedFromSearchHome ? R.anim.recents_to_search_launcher_exit : - R.anim.recents_to_launcher_exit)); + R.anim.recents_to_search_launcher_enter, + R.anim.recents_to_search_launcher_exit)); // Mark the task that is the launch target int taskStackCount = stacks.size(); @@ -264,28 +257,15 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView mEmptyView.setVisibility(View.GONE); mEmptyView.setOnClickListener(null); } - boolean showSearchBar = CMSettings.System.getInt(getContentResolver(), - CMSettings.System.RECENTS_SHOW_SEARCH_BAR, 1) == 1; - - if (mRecentsView.hasValidSearchBar()) { - if (showSearchBar) { + if (!mConfig.searchBarEnabled) { + mRecentsView.setSearchBarVisibility(View.GONE); + } else { + if (mRecentsView.hasValidSearchBar()) { mRecentsView.setSearchBarVisibility(View.VISIBLE); } else { - mRecentsView.setSearchBarVisibility(View.GONE); - } - } else { - if (showSearchBar) { refreshSearchWidgetView(); } } - - // Update search bar space height - if (showSearchBar) { - mConfig.searchBarSpaceHeightPx = getResources().getDimensionPixelSize( - R.dimen.recents_search_bar_space_height); - } else { - mConfig.searchBarSpaceHeightPx = 0; - } } // Animate the SystemUI scrims into view @@ -459,6 +439,14 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView } @Override + protected void onResume() { + if (mConfig.searchBarEnabled && mConfig.launchedFromHome) { + overridePendingTransition(0, 0); + } + super.onResume(); + } + + @Override protected void onPause() { super.onPause(); if (mAfterPauseRunnable != null) { diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java index 41d52b8..d7e8b99 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java @@ -31,6 +31,7 @@ import com.android.systemui.R; import com.android.systemui.recents.misc.Console; import com.android.systemui.recents.misc.SystemServicesProxy; +import cyanogenmod.providers.CMSettings; /** A static Recents configuration for the current context * NOTE: We should not hold any references to a Context from a static instance */ @@ -73,6 +74,7 @@ public class RecentsConfiguration { public int maxNumTasksToLoad; /** Search bar */ + public boolean searchBarEnabled = true; public int searchBarSpaceHeightPx; /** Task stack */ @@ -279,6 +281,13 @@ public class RecentsConfiguration { svelteLevel = res.getInteger(R.integer.recents_svelte_level); } + public boolean updateShowSearch(Context context) { + boolean wasEnabled = searchBarEnabled; + searchBarEnabled = CMSettings.System.getInt(context.getContentResolver(), + CMSettings.System.RECENTS_SHOW_SEARCH_BAR, 1) == 1; + return wasEnabled != searchBarEnabled; + } + /** Updates the system insets */ public void updateSystemInsets(Rect insets) { systemInsets.set(insets); 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 947c19c..64622620 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -323,7 +323,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV // Get the search bar bounds and measure the search bar layout Rect searchBarSpaceBounds = new Rect(); - if (mSearchBar != null) { + if (mSearchBar != null && mConfig.searchBarEnabled) { mConfig.getSearchBarBounds(width, height, mConfig.systemInsets.top, searchBarSpaceBounds); mSearchBar.measure( MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), MeasureSpec.EXACTLY), @@ -360,7 +360,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { // Get the search bar bounds so that we lay it out - if (mSearchBar != null) { + if (mSearchBar != null && mConfig.searchBarEnabled) { Rect searchBarSpaceBounds = new Rect(); mConfig.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(), mConfig.systemInsets.top, searchBarSpaceBounds); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java index ce5cce5..7b608bb 100755 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java @@ -1345,27 +1345,50 @@ public abstract class BaseStatusBar extends SystemUI implements View contentViewLocal = null; View bigContentViewLocal = null; View headsUpContentViewLocal = null; - String themePackageName = mCurrentTheme != null ? - mCurrentTheme.getOverlayForStatusBar() : null; + String themePackageName = mCurrentTheme != null + ? mCurrentTheme.getOverlayPkgNameForApp(sbn.getPackageName()) : null; + String statusBarThemePackageName = mCurrentTheme != null + ? mCurrentTheme.getOverlayForStatusBar() : null; + try { contentViewLocal = contentView.apply( sbn.getPackageContext(mContext), contentContainer, mOnClickHandler, - themePackageName); + statusBarThemePackageName); + + final int platformTemplateRootViewId = + com.android.internal.R.id.status_bar_latest_event_content; + final String inflationThemePackageName; + if (themePackageName != null + && !TextUtils.equals(themePackageName, statusBarThemePackageName) + && contentViewLocal.getId() != platformTemplateRootViewId) { + // This notification uses custom RemoteViews, and its app uses a different + // theme than the status bar. Re-inflate the views using the app's theme, + // as the RemoteViews likely will contain resources of the app, not the platform + inflationThemePackageName = themePackageName; + contentViewLocal = contentView.apply( + sbn.getPackageContext(mContext), + contentContainer, + mOnClickHandler, + inflationThemePackageName); + } else { + inflationThemePackageName = statusBarThemePackageName; + } + if (bigContentView != null) { bigContentViewLocal = bigContentView.apply( sbn.getPackageContext(mContext), contentContainer, mOnClickHandler, - themePackageName); + inflationThemePackageName); } if (headsUpContentView != null) { headsUpContentViewLocal = headsUpContentView.apply( sbn.getPackageContext(mContext), contentContainer, mOnClickHandler, - themePackageName); + inflationThemePackageName); } } catch (RuntimeException e) { @@ -1904,8 +1927,9 @@ public abstract class BaseStatusBar extends SystemUI implements boolean shouldInterrupt = shouldInterrupt(entry, notification); boolean alertAgain = alertAgain(entry, n); + final StatusBarNotification oldNotification = entry.notification; entry.notification = notification; - mGroupManager.onEntryUpdated(entry, entry.notification); + mGroupManager.onEntryUpdated(entry, oldNotification); boolean updateSuccessful = false; if (applyInPlace) { @@ -1947,7 +1971,9 @@ public abstract class BaseStatusBar extends SystemUI implements entry.icon.set(ic); inflateViews(entry, mStackScroller); } - updateHeadsUp(key, entry, shouldInterrupt, alertAgain); + if (mUseHeadsUp) { + updateHeadsUp(key, entry, shouldInterrupt, alertAgain); + } mNotificationData.updateRanking(ranking); updateNotifications(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java index 2233d13..ecaa809 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -353,10 +353,13 @@ public class SignalClusterView for (PhoneState state : mPhoneStates) { if (state.mMobile != null) { + state.maybeStopAnimatableDrawable(state.mMobile); state.mMobile.setImageDrawable(null); + state.mLastMobileStrengthId = -1; } if (state.mMobileType != null) { state.mMobileType.setImageDrawable(null); + state.mLastMobileTypeId = -1; } } @@ -484,6 +487,8 @@ public class SignalClusterView private final int mSubId; private boolean mMobileVisible = false; private int mMobileStrengthId = 0, mMobileTypeId = 0; + private int mLastMobileStrengthId = -1; + private int mLastMobileTypeId = -1; private boolean mIsMobileTypeIconWide; private String mMobileDescription, mMobileTypeDescription; private boolean mShowRoamingIndicator; @@ -509,25 +514,16 @@ public class SignalClusterView public boolean apply(boolean isSecondaryIcon) { if (mMobileVisible && !mIsAirplaneMode) { - mMobile.setImageResource(mMobileStrengthId); - Drawable mobileDrawable = mMobile.getDrawable(); - if (mobileDrawable instanceof Animatable) { - Animatable ad = (Animatable) mobileDrawable; - if (!ad.isRunning()) { - ad.start(); - } + if (mLastMobileStrengthId != mMobileStrengthId) { + updateAnimatableIcon(mMobile, mMobileStrengthId); + updateAnimatableIcon(mMobileDark, mMobileStrengthId); + mLastMobileStrengthId = mMobileStrengthId; } - mMobileDark.setImageResource(mMobileStrengthId); - Drawable mobileDarkDrawable = mMobileDark.getDrawable(); - if (mobileDarkDrawable instanceof Animatable) { - Animatable ad = (Animatable) mobileDarkDrawable; - if (!ad.isRunning()) { - ad.start(); - } + if (mLastMobileTypeId != mMobileTypeId) { + mMobileType.setImageResource(mMobileTypeId); + mLastMobileTypeId = mMobileTypeId; } - - mMobileType.setImageResource(mMobileTypeId); mMobileGroup.setContentDescription(mMobileTypeDescription + " " + mMobileDescription); mMobileGroup.setVisibility(View.VISIBLE); @@ -552,6 +548,32 @@ public class SignalClusterView return mMobileVisible; } + private void updateAnimatableIcon(ImageView view, int resId) { + maybeStopAnimatableDrawable(view); + view.setImageResource(resId); + maybeStartAnimatableDrawable(view); + } + + private void maybeStopAnimatableDrawable(ImageView view) { + Drawable drawable = view.getDrawable(); + if (drawable instanceof Animatable) { + Animatable ad = (Animatable) drawable; + if (ad.isRunning()) { + ad.stop(); + } + } + } + + private void maybeStartAnimatableDrawable(ImageView view) { + Drawable drawable = view.getDrawable(); + if (drawable instanceof Animatable) { + Animatable ad = (Animatable) drawable; + if (!ad.isRunning()) { + ad.start(); + } + } + } + public void populateAccessibilityEvent(AccessibilityEvent event) { if (mMobileVisible && mMobileGroup != null && mMobileGroup.getContentDescription() != null) { @@ -562,6 +584,7 @@ public class SignalClusterView public void setIconTint(int tint, float darkIntensity) { applyDarkIntensity(darkIntensity, mMobile, mMobileDark); setTint(mMobileType, tint); + setTint(mMobileRoaming, tint); } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java index 1991602..40e4330 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/VisualizerView.java @@ -26,19 +26,21 @@ import android.media.audiofx.Visualizer; import android.os.AsyncTask; import android.os.Handler; import android.os.UserHandle; -import android.provider.Settings; import android.support.v7.graphics.Palette; import android.util.AttributeSet; +import android.util.Log; import android.view.View; + import com.android.systemui.cm.UserContentObserver; import com.android.systemui.statusbar.policy.KeyguardMonitor; import cyanogenmod.providers.CMSettings; -import java.util.Arrays; - public class VisualizerView extends View implements Palette.PaletteAsyncListener, KeyguardMonitor.Callback { + private static final String TAG = VisualizerView.class.getSimpleName(); + private static final boolean DEBUG = false; + private Paint mPaint; private Visualizer mVisualizer; private ObjectAnimator mVisualizerColorAnimator; @@ -89,9 +91,14 @@ public class VisualizerView extends View implements Palette.PaletteAsyncListener private final Runnable mLinkVisualizer = new Runnable() { @Override public void run() { + if (DEBUG) { + Log.w(TAG, "+++ mLinkVisualizer run()"); + } + try { mVisualizer = new Visualizer(0); } catch (Exception e) { + Log.e(TAG, "error initializing visualizer", e); return; } @@ -101,17 +108,26 @@ public class VisualizerView extends View implements Palette.PaletteAsyncListener false, true); mVisualizer.setEnabled(true); + if (DEBUG) { + Log.w(TAG, "--- mLinkVisualizer run()"); + } } }; private final Runnable mUnlinkVisualizer = new Runnable() { @Override public void run() { + if (DEBUG) { + Log.w(TAG, "+++ mUnlinkVisualizer run(), mVisualizer: " + mVisualizer); + } if (mVisualizer != null) { mVisualizer.setEnabled(false); mVisualizer.release(); mVisualizer = null; } + if (DEBUG) { + Log.w(TAG, "--- mUninkVisualizer run()"); + } } }; @@ -223,6 +239,7 @@ public class VisualizerView extends View implements Palette.PaletteAsyncListener mKeyguardMonitor = kgm; if (isAttachedToWindow()) { // otherwise we might never register ourselves + mKeyguardMonitor.removeCallback(this); mKeyguardMonitor.addCallback(this); updateViewVisibility(); } @@ -230,6 +247,9 @@ public class VisualizerView extends View implements Palette.PaletteAsyncListener public void setVisible(boolean visible) { if (mVisible != visible) { + if (DEBUG) { + Log.i(TAG, "setVisible() called with visible = [" + visible + "]"); + } mVisible = visible; checkStateChanged(); } @@ -237,6 +257,9 @@ public class VisualizerView extends View implements Palette.PaletteAsyncListener public void setDozing(boolean dozing) { if (mDozing != dozing) { + if (DEBUG) { + Log.i(TAG, "setDozing() called with dozing = [" + dozing + "]"); + } mDozing = dozing; checkStateChanged(); } @@ -244,6 +267,9 @@ public class VisualizerView extends View implements Palette.PaletteAsyncListener public void setPlaying(boolean playing) { if (mPlaying != playing) { + if (DEBUG) { + Log.i(TAG, "setPlaying() called with playing = [" + playing + "]"); + } mPlaying = playing; checkStateChanged(); } @@ -251,6 +277,9 @@ public class VisualizerView extends View implements Palette.PaletteAsyncListener public void setPowerSaveMode(boolean powerSaveMode) { if (mPowerSaveMode != powerSaveMode) { + if (DEBUG) { + Log.i(TAG, "setPowerSaveMode() called with powerSaveMode = [" + powerSaveMode + "]"); + } mPowerSaveMode = powerSaveMode; checkStateChanged(); } @@ -258,6 +287,9 @@ public class VisualizerView extends View implements Palette.PaletteAsyncListener public void setOccluded(boolean occluded) { if (mOccluded != occluded) { + if (DEBUG) { + Log.i(TAG, "setOccluded() called with occluded = [" + occluded + "]"); + } mOccluded = occluded; checkStateChanged(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java index 2912963..7135836 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java @@ -173,7 +173,7 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback { if (DEBUG_FP_WAKELOCK) { Log.i(TAG, "fp wakelock: Authenticated, waking up..."); } - mPowerManager.wakeUp(SystemClock.uptimeMillis()); + mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.policy:FINGERPRINT"); } releaseFingerprintWakeLock(); switch (mMode) { 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 ecc3a9b..d95a46a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -221,6 +221,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mShortcutHelper = new LockscreenShortcutsHelper(mContext, this); watchForCameraPolicyChanges(); updateCameraVisibility(); + updateLeftButtonVisibility(); mUnlockMethodCache = UnlockMethodCache.getInstance(getContext()); mUnlockMethodCache.addListener(this); mLockIcon.update(); @@ -257,6 +258,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mCameraImageView.setContentDescription(contentDescription); mCameraImageView.setDefaultFilter(shouldGrayScale ? mGrayScaleFilter : null); updateCameraVisibility(); + updateLeftButtonVisibility(); } private void initAccessibility() { @@ -299,11 +301,13 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL public void setPhoneStatusBar(PhoneStatusBar phoneStatusBar) { mPhoneStatusBar = phoneStatusBar; updateCameraVisibility(); // in case onFinishInflate() was called too early + updateLeftButtonVisibility(); } public void setUserSetupComplete(boolean userSetupComplete) { mUserSetupComplete = userSetupComplete; updateCameraVisibility(); + updateLeftButtonVisibility(); updateLeftAffordanceIcon(); } @@ -324,6 +328,21 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL KeyguardUpdateMonitor.getCurrentUser()); } + private void updateLeftButtonVisibility() { + if (mLeftAffordanceView == null) { + return; + } + boolean visible = mUserSetupComplete; + if (visible) { + if (isTargetCustom(Shortcuts.LEFT_SHORTCUT)) { + visible = !mShortcutHelper.isTargetEmpty(Shortcuts.LEFT_SHORTCUT); + } else { + // Display left shortcut + } + } + mLeftAffordanceView.setVisibility(visible ? View.VISIBLE : View.GONE); + } + private void updateCameraVisibility() { if (mCameraImageView == null) { // Things are not set up yet; reply hazy, ask again later @@ -364,6 +383,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mLeftAffordanceView.setImageDrawable(drawable); mLeftAffordanceView.setContentDescription(contentDescription); mLeftAffordanceView.setDefaultFilter(shouldGrayScale ? mGrayScaleFilter : null); + updateLeftButtonVisibility(); } public boolean isLeftVoiceAssist() { @@ -592,6 +612,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL if (changedView == this && visibility == VISIBLE) { mLockIcon.update(); updateCameraVisibility(); + updateLeftButtonVisibility(); } } @@ -628,6 +649,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL public void onUnlockMethodStateChanged() { mLockIcon.update(); updateCameraVisibility(); + updateLeftButtonVisibility(); } private void inflateCameraPreview() { @@ -699,6 +721,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL @Override public void run() { updateCameraVisibility(); + updateLeftButtonVisibility(); } }); } @@ -709,6 +732,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL @Override public void onUserSwitchComplete(int userId) { updateCameraVisibility(); + updateLeftButtonVisibility(); } @Override 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 395f350..65e2096 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -32,6 +32,8 @@ import com.android.keyguard.R; import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.DejankUtils; +import org.cyanogenmod.internal.util.CmLockPatternUtils; + import static com.android.keyguard.KeyguardHostView.OnDismissAction; import static com.android.keyguard.KeyguardSecurityModel.SecurityMode; @@ -40,9 +42,14 @@ import static com.android.keyguard.KeyguardSecurityModel.SecurityMode; */ public class KeyguardBouncer { + public static final int UNLOCK_SEQUENCE_DEFAULT = 0; + public static final int UNLOCK_SEQUENCE_BOUNCER_FIRST = 1; + public static final int UNLOCK_SEQUENCE_FORCE_BOUNCER = 2; + private Context mContext; private ViewMediatorCallback mCallback; private LockPatternUtils mLockPatternUtils; + private CmLockPatternUtils mCmLockPatternUtils; private ViewGroup mContainer; private StatusBarWindowManager mWindowManager; private KeyguardHostView mKeyguardView; @@ -65,6 +72,7 @@ public class KeyguardBouncer { mLockPatternUtils = lockPatternUtils; mContainer = container; mWindowManager = windowManager; + mCmLockPatternUtils = new CmLockPatternUtils(mContext); KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback); } @@ -207,28 +215,42 @@ public class KeyguardBouncer { } /** - * @return True if and only if the security method should be shown before showing the - * notifications on Keyguard, like SIM PIN/PUK. + * @return Whether the bouncer should be shown first, this could be because of SIM PIN/PUK + * or it just could be chosen to be shown first. */ - public boolean needsFullscreenBouncer() { + public int needsFullscreenBouncer() { ensureView(); if (mKeyguardView != null) { SecurityMode mode = mKeyguardView.getSecurityMode(); - return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk; + if (mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk) + return UNLOCK_SEQUENCE_FORCE_BOUNCER; + // "Bouncer first" mode currently only available to some security methods. + else if ((mode == SecurityMode.Pattern || mode == SecurityMode.Password + || mode == SecurityMode.PIN) && (mLockPatternUtils != null && + mCmLockPatternUtils.shouldPassToSecurityView( + KeyguardUpdateMonitor.getCurrentUser()))) + return UNLOCK_SEQUENCE_BOUNCER_FIRST; } - return false; + return UNLOCK_SEQUENCE_DEFAULT; } /** * Like {@link #needsFullscreenBouncer}, but uses the currently visible security method, which * makes this method much faster. */ - public boolean isFullscreenBouncer() { + public int isFullscreenBouncer() { if (mKeyguardView != null) { SecurityMode mode = mKeyguardView.getCurrentSecurityMode(); - return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk; + if (mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk) + return UNLOCK_SEQUENCE_FORCE_BOUNCER; + // "Bouncer first" mode currently only available to some security methods. + else if ((mode == SecurityMode.Pattern || mode == SecurityMode.Password + || mode == SecurityMode.PIN) && (mLockPatternUtils != null && + mCmLockPatternUtils.shouldPassToSecurityView( + KeyguardUpdateMonitor.getCurrentUser()))) + return UNLOCK_SEQUENCE_BOUNCER_FIRST; } - return false; + return UNLOCK_SEQUENCE_DEFAULT; } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java index 7524732..ec307de 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java @@ -1,6 +1,6 @@ /* * Copyright (C) 2014 The Android Open Source Project - * + * Copyright (C) 2016 The CyanogenMod 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 @@ -31,8 +31,10 @@ import android.widget.TextView; import com.android.systemui.BatteryLevelTextView; import com.android.systemui.BatteryMeterView; +import com.android.systemui.DockBatteryMeterView; import com.android.systemui.R; import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.DockBatteryController; import com.android.systemui.statusbar.policy.KeyguardUserSwitcher; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.statusbar.policy.UserSwitcherController; @@ -49,8 +51,8 @@ public class KeyguardStatusBarView extends RelativeLayout { private MultiUserSwitch mMultiUserSwitch; private ImageView mMultiUserAvatar; private BatteryLevelTextView mBatteryLevel; + private BatteryLevelTextView mDockBatteryLevel; - private BatteryController mBatteryController; private KeyguardUserSwitcher mKeyguardUserSwitcher; private int mSystemIconsSwitcherHiddenExpandedMargin; @@ -69,6 +71,7 @@ public class KeyguardStatusBarView extends RelativeLayout { mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch); mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar); mBatteryLevel = (BatteryLevelTextView) findViewById(R.id.battery_level_text); + mDockBatteryLevel = (BatteryLevelTextView) findViewById(R.id.dock_battery_level_text); mCarrierLabel = (TextView) findViewById(R.id.keyguard_carrier_text); loadDimens(); mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(), @@ -110,6 +113,9 @@ public class KeyguardStatusBarView extends RelativeLayout { removeView(mMultiUserSwitch); } mBatteryLevel.setVisibility(View.VISIBLE); + if (mDockBatteryLevel != null) { + mDockBatteryLevel.setVisibility(View.VISIBLE); + } } private void updateSystemIconsLayoutParams() { @@ -130,9 +136,26 @@ public class KeyguardStatusBarView extends RelativeLayout { } public void setBatteryController(BatteryController batteryController) { - mBatteryController = batteryController; - ((BatteryMeterView) findViewById(R.id.battery)).setBatteryController(batteryController); - mBatteryLevel.setBatteryController(batteryController); + BatteryMeterView v = ((BatteryMeterView) findViewById(R.id.battery)); + v.setBatteryStateRegistar(batteryController); + v.setBatteryController(batteryController); + mBatteryLevel.setBatteryStateRegistar(batteryController); + } + + public void setDockBatteryController(DockBatteryController dockBatteryController) { + DockBatteryMeterView v = ((DockBatteryMeterView) findViewById(R.id.dock_battery)); + if (dockBatteryController != null) { + v.setBatteryStateRegistar(dockBatteryController); + mDockBatteryLevel.setBatteryStateRegistar(dockBatteryController); + } else { + if (v != null ) { + removeView(v); + } + if (mDockBatteryLevel != null) { + removeView(mDockBatteryLevel); + mDockBatteryLevel = null; + } + } } public void setUserSwitcherController(UserSwitcherController controller) { 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 b3ba926..c10f45b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java @@ -34,15 +34,14 @@ import android.database.ContentObserver; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Handler; import android.os.Message; import android.os.RemoteException; import android.os.UserHandle; -import android.provider.Settings; import android.util.AttributeSet; import android.util.Log; import android.view.Display; -import android.view.Gravity; import android.view.MotionEvent; import android.view.Surface; import android.view.View; @@ -50,18 +49,15 @@ import android.view.ViewGroup; import android.view.ViewRootImpl; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; -import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import com.android.systemui.R; -import com.android.systemui.cm.UserContentObserver; import com.android.systemui.statusbar.policy.DeadZone; import com.android.systemui.statusbar.policy.KeyButtonView; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.util.ArrayList; import cyanogenmod.providers.CMSettings; @@ -227,7 +223,8 @@ public class NavigationBarView extends LinearLayout { mBarTransitions = new NavigationBarTransitions(this); mNavBarReceiver = new NavBarReceiver(); - getContext().registerReceiver(mNavBarReceiver, new IntentFilter(NAVBAR_EDIT_ACTION)); + getContext().registerReceiverAsUser(mNavBarReceiver, UserHandle.ALL, + new IntentFilter(NAVBAR_EDIT_ACTION), null, null); mSettingsObserver = new SettingsObserver(new Handler()); } @@ -425,6 +422,19 @@ public class NavigationBarView extends LinearLayout { setSideButtonVisibility(false, -1); } } + } else { + setVisibleOrGone(getCurrentView().findViewById(R.id.dpad_left), false); + setVisibleOrGone(getCurrentView().findViewById(R.id.dpad_right), false); + View one = getCurrentView().findViewById(mVertical ? R.id.six : R.id.one); + View six = getCurrentView().findViewById(mVertical ? R.id.one : R.id.six); + if (getSideButtonVisibility(true) != -1) { + one.setVisibility(getSideButtonVisibility(true)); + setSideButtonVisibility(true, - 1); + } + if (getSideButtonVisibility(false) != -1) { + six.setVisibility(getSideButtonVisibility(false)); + setSideButtonVisibility(false, -1); + } } } @@ -879,19 +889,17 @@ public class NavigationBarView extends LinearLayout { mEditBar.updateKeys(); removeButtonListeners(); updateButtonListeners(); - setDisabledFlags(mDisabledFlags, true /* force */); + updateShowDpadKeys(); setMenuVisibility(mShowMenu, true); } - private class SettingsObserver extends UserContentObserver { + private class SettingsObserver extends ContentObserver { SettingsObserver(Handler handler) { super(handler); } - @Override public void observe() { - super.observe(); ContentResolver resolver = getContext().getContentResolver(); resolver.registerContentObserver( CMSettings.System.getUriFor(CMSettings.System.NAVIGATION_BAR_MENU_ARROW_KEYS), @@ -901,23 +909,20 @@ public class NavigationBarView extends LinearLayout { onChange(false); } - @Override public void unobserve() { - super.unobserve(); getContext().getContentResolver().unregisterContentObserver(this); } @Override - protected void update() { - mShowDpadArrowKeys = CMSettings.System.getIntForUser(getContext().getContentResolver(), - CMSettings.System.NAVIGATION_BAR_MENU_ARROW_KEYS, 0, UserHandle.USER_CURRENT) != 0; - // reset saved side button visibilities - for (int i = 0; i < mSideButtonVisibilities.length; i++) { - for (int j = 0; j < mSideButtonVisibilities[i].length; j++) { - mSideButtonVisibilities[i][j] = -1; - } - } - setNavigationIconHints(mNavigationIconHints, true); + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); + updateShowDpadKeys(); } } + + private void updateShowDpadKeys() { + mShowDpadArrowKeys = CMSettings.System.getIntForUser(getContext().getContentResolver(), + CMSettings.System.NAVIGATION_BAR_MENU_ARROW_KEYS, 0, UserHandle.USER_CURRENT) != 0; + setNavigationIconHints(mNavigationIconHints, true); + } } 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 6adbe85..aaa7019 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -1116,7 +1116,8 @@ public class NotificationPanelView extends PanelView implements mAfforanceHelper.updatePreviews(); } } - if (keyguardShowing) { + if (statusBarState == StatusBarState.KEYGUARD || + statusBarState == StatusBarState.SHADE_LOCKED) { updateDozingVisibilities(false /* animate */); if (mThirdPartyKeyguardViewComponent != null) { if (mKeyguardExternalView == null) { @@ -1237,7 +1238,8 @@ public class NotificationPanelView extends PanelView implements @Override public void run() { mStatusBar.showKeyguard(); - mStatusBar.startActivity(intent, true); + mStatusBar.startActivityDismissingKeyguard(intent, false, true, true, + null); } }); } @@ -2540,7 +2542,7 @@ public class NotificationPanelView extends PanelView implements * @param x the x-coordinate the touch event */ private void updateVerticalPanelPosition(float x) { - if (mNotificationStackScroller.getWidth() * 1.75f > getWidth()) { + if (mNotificationStackScroller.getWidth() * 1.75f >= getWidth()) { resetVerticalPanelPosition(); return; } 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 f5cdcd1..e5711b8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -42,8 +42,6 @@ import com.android.systemui.statusbar.FlingAnimationUtils; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.policy.HeadsUpManager; -import cyanogenmod.power.PerformanceManager; - import java.io.FileDescriptor; import java.io.PrintWriter; @@ -90,8 +88,6 @@ public abstract class PanelView extends FrameLayout { private VelocityTrackerInterface mVelocityTracker; private FlingAnimationUtils mFlingAnimationUtils; - private final PerformanceManager mPerf; - private boolean mUpdateExpandOnLayout; private View.OnLayoutChangeListener mLayoutChangeListener = new OnLayoutChangeListener() { @Override @@ -222,8 +218,6 @@ public abstract class PanelView extends FrameLayout { mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in); mBounceInterpolator = new BounceInterpolator(); - - mPerf = PerformanceManager.getInstance(context); } protected void loadDimens() { @@ -695,8 +689,6 @@ public abstract class PanelView extends FrameLayout { } } - mPerf.cpuBoost((int)animator.getDuration() * 1000); - animator.addListener(new AnimatorListenerAdapter() { private boolean mCancelled; 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 41fd86a..adff973 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -42,7 +42,6 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.Configuration; -import android.content.res.ThemeChangeRequest.RequestType; import android.content.res.ThemeConfig; import android.content.res.Resources; import android.database.ContentObserver; @@ -65,6 +64,7 @@ import android.media.session.MediaSession; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; import android.os.AsyncTask; +import android.os.BatteryManager; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; @@ -125,6 +125,7 @@ import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.BatteryMeterView; import com.android.systemui.BatteryLevelTextView; import com.android.systemui.DemoMode; +import com.android.systemui.DockBatteryMeterView; import com.android.systemui.EventLogConstants; import com.android.systemui.EventLogTags; import com.android.systemui.Prefs; @@ -161,10 +162,11 @@ import com.android.systemui.statusbar.VisualizerView; import com.android.systemui.statusbar.phone.UnlockMethodCache.OnUnlockMethodChangedListener; import com.android.systemui.statusbar.policy.AccessibilityController; import com.android.systemui.statusbar.policy.BatteryController; -import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; +import com.android.systemui.statusbar.policy.BatteryStateRegistar.BatteryStateChangeCallback; import com.android.systemui.statusbar.policy.BluetoothControllerImpl; import com.android.systemui.statusbar.policy.BrightnessMirrorController; import com.android.systemui.statusbar.policy.CastControllerImpl; +import com.android.systemui.statusbar.policy.DockBatteryController; import com.android.systemui.statusbar.policy.FlashlightController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.statusbar.policy.HotspotControllerImpl; @@ -188,6 +190,7 @@ import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChil import com.android.systemui.statusbar.stack.StackStateAnimator; import com.android.systemui.statusbar.stack.StackViewState; import com.android.systemui.volume.VolumeComponent; +import cyanogenmod.app.CMContextConstants; import cyanogenmod.app.CustomTileListenerService; import cyanogenmod.app.StatusBarPanelCustomTile; @@ -216,6 +219,7 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARE import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING; import cyanogenmod.providers.CMSettings; +import cyanogenmod.themes.IThemeService; public class PhoneStatusBar extends BaseStatusBar implements DemoMode, DragDownHelper.DragDownCallback, ActivityStarter, OnUnlockMethodChangedListener, @@ -241,7 +245,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private static final int MSG_CLOSE_PANELS = 1001; private static final int MSG_OPEN_SETTINGS_PANEL = 1002; private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003; - private static final int MSG_UPDATE_NOTIFICATIONS = 1004; // 1020-1040 reserved for BaseStatusBar // Time after we abort the launch transition. @@ -297,7 +300,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // These are no longer handled by the policy, because we need custom strategies for them BluetoothControllerImpl mBluetoothController; SecurityControllerImpl mSecurityController; + BatteryManager mBatteryManager; BatteryController mBatteryController; + DockBatteryController mDockBatteryController; LocationControllerImpl mLocationController; NetworkControllerImpl mNetworkController; HotspotControllerImpl mHotspotController; @@ -420,6 +425,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private int mNavigationIconHints = 0; private HandlerThread mHandlerThread; + private IThemeService mThemeService; + private long mLastThemeChangeTime = 0; + Runnable mLongPressBrightnessChange = new Runnable() { @Override public void run() { @@ -861,6 +869,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mScreenPinningRequest = new ScreenPinningRequest(mContext); updateCustomRecentsLongPressHandler(true); + + mThemeService = IThemeService.Stub.asInterface(ServiceManager.getService( + CMContextConstants.CM_THEME_SERVICE)); } // ================================================================================ @@ -1046,6 +1057,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mLocationController = new LocationControllerImpl(mContext, mHandlerThread.getLooper()); // will post a notification } + if (mBatteryManager == null) { + mBatteryManager = (BatteryManager) mContext.getSystemService(Context.BATTERY_SERVICE); + } if (mBatteryController == null) { mBatteryController = new BatteryController(mContext, mHandler); mBatteryController.addStateChangedCallback(new BatteryStateChangeCallback() { @@ -1058,7 +1072,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } @Override - public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { + public void onBatteryLevelChanged(boolean present, int level, + boolean pluggedIn, boolean charging) { // noop } @@ -1068,6 +1083,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } }); } + if (mBatteryManager.isDockBatterySupported()) { + if (mDockBatteryController == null) { + mDockBatteryController = new DockBatteryController(mContext, mHandler); + } + } if (mNetworkController == null) { mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper()); } @@ -1265,13 +1285,36 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mUserInfoController.reloadUserInfo(); mHeader.setBatteryController(mBatteryController); + BatteryMeterView batteryMeterView = ((BatteryMeterView) mStatusBarView.findViewById(R.id.battery)); + batteryMeterView.setBatteryStateRegistar(mBatteryController); batteryMeterView.setBatteryController(mBatteryController); batteryMeterView.setAnimationsEnabled(false); ((BatteryLevelTextView) mStatusBarView.findViewById(R.id.battery_level_text)) - .setBatteryController(mBatteryController); + .setBatteryStateRegistar(mBatteryController); mKeyguardStatusBar.setBatteryController(mBatteryController); + mHeader.setDockBatteryController(mDockBatteryController); + mKeyguardStatusBar.setDockBatteryController(mDockBatteryController); + if (mDockBatteryController != null) { + DockBatteryMeterView dockBatteryMeterView = + ((DockBatteryMeterView) mStatusBarView.findViewById(R.id.dock_battery)); + dockBatteryMeterView.setBatteryStateRegistar(mDockBatteryController); + ((BatteryLevelTextView) mStatusBarView.findViewById(R.id.dock_battery_level_text)) + .setBatteryStateRegistar(mDockBatteryController); + } else { + DockBatteryMeterView dockBatteryMeterView = + (DockBatteryMeterView) mStatusBarView.findViewById(R.id.dock_battery); + if (dockBatteryMeterView != null) { + mStatusBarView.removeView(dockBatteryMeterView); + } + BatteryLevelTextView dockBatteryLevel = + (BatteryLevelTextView) mStatusBarView.findViewById(R.id.dock_battery_level_text); + if (dockBatteryLevel != null) { + mStatusBarView.removeView(dockBatteryLevel); + } + } + mVisualizerView.setKeyguardMonitor(mKeyguardMonitor); mHeader.setNextAlarmController(mNextAlarmController); mHeader.setWeatherController(mWeatherController); @@ -1289,6 +1332,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_KEYGUARD_WALLPAPER_CHANGED); + filter.addAction(cyanogenmod.content.Intent.ACTION_SCREEN_CAMERA_GESTURE); context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); IntentFilter demoFilter = new IntentFilter(); @@ -1913,7 +1957,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, return entry.row.getParent() instanceof NotificationStackScrollLayout; } - private void handleUpdateNotifications() { + @Override + protected void updateNotifications() { mNotificationData.filterAndSort(); updateNotificationShade(); @@ -1921,13 +1966,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } @Override - protected void updateNotifications() { - if (!mHandler.hasMessages(MSG_UPDATE_NOTIFICATIONS)) { - mHandler.sendEmptyMessage(MSG_UPDATE_NOTIFICATIONS); - } - } - - @Override protected void updateRowStates() { super.updateRowStates(); mNotificationPanel.notifyVisibleChildrenChanged(); @@ -2144,23 +2182,20 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } - // apply user lockscreen image - if (mMediaMetadata == null && backdropBitmap == null) { - backdropBitmap = mKeyguardWallpaper; - } - - boolean keyguardVisible = (mState != StatusBarState.SHADE); + // HACK: Consider keyguard as visible if showing sim pin security screen + KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext); + boolean keyguardVisible = mState != StatusBarState.SHADE || updateMonitor.isSimPinSecure(); if (!mKeyguardFadingAway && keyguardVisible && backdropBitmap != null && mScreenOn) { // if there's album art, ensure visualizer is visible - mVisualizerView.setVisible(true); mVisualizerView.setPlaying(mMediaController != null && mMediaController.getPlaybackState() != null && mMediaController.getPlaybackState().getState() == PlaybackState.STATE_PLAYING); } - if (backdropBitmap == null && mMediaMetadata == null) { + // apply user lockscreen image + if (backdropBitmap == null && !mNotificationPanel.hasExternalKeyguardView()) { backdropBitmap = mKeyguardWallpaper; } @@ -2578,9 +2613,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, case MSG_LAUNCH_TRANSITION_TIMEOUT: onLaunchTransitionTimeout(); break; - case MSG_UPDATE_NOTIFICATIONS: - handleUpdateNotifications(); - break; } } } @@ -3352,6 +3384,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mBatteryController != null) { mBatteryController.dump(fd, pw, args); } + if (mDockBatteryController != null) { + mDockBatteryController.dump(fd, pw, args); + } if (mNextAlarmController != null) { mNextAlarmController.dump(fd, pw, args); } @@ -3421,10 +3456,16 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, final boolean dismissShade, final Callback callback) { - if (onlyProvisioned && !isDeviceProvisioned()) return; - final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity( mContext, intent, mCurrentUserId); + startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, afterKeyguardGone, + callback); + } + + public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned, + final boolean dismissShade, final boolean afterKeyguardGone, final Callback callback) { + if (onlyProvisioned && !isDeviceProvisioned()) return; + final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing(); Runnable runnable = new Runnable() { public void run() { @@ -3521,6 +3562,17 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, Context.WALLPAPER_SERVICE); mKeyguardWallpaper = wm.getKeyguardBitmap(); updateMediaMetaData(true); + } else if (cyanogenmod.content.Intent.ACTION_SCREEN_CAMERA_GESTURE.equals(action)) { + boolean userSetupComplete = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.USER_SETUP_COMPLETE, 0) != 0; + if (!userSetupComplete) { + if (DEBUG) Log.d(TAG, String.format( + "userSetupComplete = %s, ignoring camera launch gesture.", + userSetupComplete)); + return; + } + + onCameraLaunchGestureDetected(StatusBarManager.CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE); } } }; @@ -3644,6 +3696,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mBatteryController != null) { mBatteryController.setUserId(mCurrentUserId); } + if (mDockBatteryController != null) { + mDockBatteryController.setUserId(mCurrentUserId); + } } private void resetUserSetupObserver() { @@ -3720,14 +3775,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, int nNotifs = mNotificationData.size(); ArrayList<Pair<String, StatusBarNotification>> notifications = new ArrayList<>(nNotifs); copyNotifications(notifications, mNotificationData); - // now remove all the notification views since we'll be re-inflating these with the copied - // data - for (int i = 0; i < nNotifs; i++) { - final NotificationData.Entry entry = mNotificationData.get(i); - if (entry != null) { - removeNotificationViews(entry.key, rankingMap); - } - } + // now remove all the notifications since we'll be re-creating these with the copied data + mNotificationData.clear(); if (mCustomTileListenerService != null) { try { @@ -3788,6 +3837,13 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, // this will make sure the keyguard is showing showKeyguard(); } + + // update mLastThemeChangeTime + try { + mLastThemeChangeTime = mThemeService.getLastThemeChangeTime(); + } catch (RemoteException e) { + /* ignore */ + } } private void removeAllViews(ViewGroup parent) { @@ -3841,8 +3897,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, /** * Determines if we need to recreate the status bar due to a theme change. We currently - * check if the overlay for the status bar, fonts, or icons, or forced update count have - * changed. + * check if the overlay for the status bar, fonts, or icons, or last theme change time is + * greater than mLastThemeChangeTime * * @param oldTheme * @param newTheme @@ -3855,17 +3911,24 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, final String overlay = newTheme.getOverlayForStatusBar(); final String icons = newTheme.getIconPackPkgName(); final String fonts = newTheme.getFontPkgName(); + boolean isNewThemeChange = false; + try { + isNewThemeChange = mLastThemeChangeTime < mThemeService.getLastThemeChangeTime(); + } catch (RemoteException e) { + /* ignore */ + } return oldTheme == null || (overlay != null && !overlay.equals(oldTheme.getOverlayForStatusBar()) || (fonts != null && !fonts.equals(oldTheme.getFontPkgName())) || (icons != null && !icons.equals(oldTheme.getIconPackPkgName())) || - newTheme.getLastThemeChangeRequestType() == RequestType.THEME_UPDATED); + isNewThemeChange); } /** * Determines if we need to update the navbar resources due to a theme change. We currently - * check if the overlay for the navbar, or request type is {@link RequestType.THEME_UPDATED}. + * check if the overlay for the navbar, or last theme change time is greater than + * mLastThemeChangeTime * * @param oldTheme * @param newTheme @@ -3876,10 +3939,16 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (newTheme == null) return false; final String overlay = newTheme.getOverlayForNavBar(); + boolean isNewThemeChange = false; + try { + isNewThemeChange = mLastThemeChangeTime < mThemeService.getLastThemeChangeTime(); + } catch (RemoteException e) { + /* ignore */ + } return oldTheme == null || (overlay != null && !overlay.equals(oldTheme.getOverlayForNavBar()) || - newTheme.getLastThemeChangeRequestType() == RequestType.THEME_UPDATED); + isNewThemeChange); } protected void loadDimens() { @@ -4157,6 +4226,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } if (modeChange || command.equals(COMMAND_BATTERY)) { dispatchDemoCommandToView(command, args, R.id.battery); + dispatchDemoCommandToView(command, args, R.id.dock_battery); } if (modeChange || command.equals(COMMAND_STATUS)) { mIconController.dispatchDemoCommand(command, args); @@ -4439,7 +4509,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, - StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION, StatusBarIconController.DEFAULT_TINT_ANIMATION_DURATION); disable(mDisabledUnmodified1, mDisabledUnmodified2, fadeoutDuration > 0 /* animate */); - mVisualizerView.setVisible(false); } public boolean isKeyguardFadingAway() { @@ -4510,7 +4579,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public void updateStackScrollerState(boolean goingToFullShade) { if (mStackScroller == null) return; boolean onKeyguard = mState == StatusBarState.KEYGUARD; - mStackScroller.setHideSensitive(isLockscreenPublicMode(), goingToFullShade); + mStackScroller.setHideSensitive(isLockscreenPublicMode() + || (!userAllowsPrivateNotificationsInPublic(mCurrentUserId) && onKeyguard), + goingToFullShade); mStackScroller.setDimmed(onKeyguard, false /* animate */); mStackScroller.setExpandingEnabled(!onKeyguard); ActivatableNotificationView activatedChild = mStackScroller.getActivatedChild(); @@ -4798,7 +4869,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, mWakeUpTouchLocation = null; mStackScroller.setAnimationsEnabled(false); updateVisibleToUser(); - mVisualizerView.setVisible(false); + if (mQSTileHost.isEditing()) { + mQSTileHost.setEditing(false); + } if (mLaunchCameraOnFinishedGoingToSleep) { mLaunchCameraOnFinishedGoingToSleep = false; @@ -4844,6 +4917,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } public void onScreenTurnedOff() { + mVisualizerView.setVisible(false); if (mNotificationPanel.hasExternalKeyguardView()) { mNotificationPanel.getExternalKeyguardView().onScreenTurnedOff(); } @@ -5211,7 +5285,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, pm.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:CAMERA_GESTURE"); mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested(); } - vibrateForCameraGesture(); + if (source != StatusBarManager.CAMERA_LAUNCH_SOURCE_SCREEN_GESTURE) { + vibrateForCameraGesture(); + } if (!mStatusBarKeyguardViewManager.isShowing()) { startActivity(KeyguardBottomAreaView.INSECURE_CAMERA_INTENT, true /* dismissShade */); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java index c4ce350..b776a9f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java @@ -42,6 +42,7 @@ import com.android.systemui.qs.tiles.AirplaneModeTile; import com.android.systemui.qs.tiles.AmbientDisplayTile; import com.android.systemui.qs.tiles.BatterySaverTile; import com.android.systemui.qs.tiles.BluetoothTile; +import com.android.systemui.qs.tiles.CaffeineTile; import com.android.systemui.qs.tiles.CastTile; import com.android.systemui.qs.tiles.CellularTile; import com.android.systemui.qs.tiles.ColorInversionTile; @@ -363,6 +364,7 @@ public class QSTileHost implements QSTile.Host, Tunable { else if (tileSpec.equals("live_display")) return new LiveDisplayTile(this); else if (tileSpec.equals("heads_up")) return new HeadsUpTile(this); else if (tileSpec.equals("battery_saver")) return new BatterySaverTile(this); + else if (tileSpec.equals("caffeine")) return new CaffeineTile(this); else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec); else throw new IllegalArgumentException("Bad tile spec: " + tileSpec); } @@ -456,6 +458,7 @@ public class QSTileHost implements QSTile.Host, Tunable { else if (spec.equals("live_display")) return R.string.live_display_title; else if (spec.equals("heads_up")) return R.string.quick_settings_heads_up_label; else if (spec.equals("battery_saver")) return R.string.quick_settings_battery_saver_label; + else if (spec.equals("caffeine")) return R.string.quick_settings_caffeine_label; return 0; } @@ -486,6 +489,7 @@ public class QSTileHost implements QSTile.Host, Tunable { else if (spec.equals("live_display")) return R.drawable.ic_livedisplay_auto; else if (spec.equals("heads_up")) return R.drawable.ic_qs_heads_up_on; else if (spec.equals("battery_saver")) return R.drawable.ic_qs_battery_saver_on; + else if (spec.equals("caffeine")) return R.drawable.ic_qs_caffeine_on; return 0; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java index 27c8a4d..339d469 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java @@ -17,9 +17,7 @@ package com.android.systemui.statusbar.phone; import android.app.ActivityManager; -import android.app.ActivityManagerNative; import android.app.AlarmManager; -import android.app.IUserSwitchObserver; import android.app.PendingIntent; import android.content.ContentUris; import android.content.ContentResolver; @@ -58,6 +56,7 @@ import android.widget.Toast; import com.android.keyguard.KeyguardStatusView; import com.android.systemui.BatteryLevelTextView; import com.android.systemui.BatteryMeterView; +import com.android.systemui.DockBatteryMeterView; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; import com.android.systemui.cm.UserContentObserver; @@ -65,6 +64,7 @@ import com.android.systemui.qs.QSDragPanel; import com.android.systemui.qs.QSPanel; import com.android.systemui.qs.QSTile; import com.android.systemui.statusbar.policy.BatteryController; +import com.android.systemui.statusbar.policy.DockBatteryController; import com.android.systemui.statusbar.policy.NetworkControllerImpl.EmergencyListener; import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.UserInfoController; @@ -108,6 +108,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private ImageView mQsDetailHeaderProgress; private TextView mEmergencyCallsOnly; private BatteryLevelTextView mBatteryLevel; + private BatteryLevelTextView mDockBatteryLevel; private TextView mAlarmStatus; private TextView mWeatherLine1, mWeatherLine2; private TextView mEditTileDoneText; @@ -138,7 +139,6 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL private float mAvatarCollapsedScaleFactor; private ActivityStarter mActivityStarter; - private BatteryController mBatteryController; private NextAlarmController mNextAlarmController; private WeatherController mWeatherController; private QSDragPanel mQSPanel; @@ -193,6 +193,7 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress); mEmergencyCallsOnly = (TextView) findViewById(R.id.header_emergency_calls_only); mBatteryLevel = (BatteryLevelTextView) findViewById(R.id.battery_level_text); + mDockBatteryLevel = (BatteryLevelTextView) findViewById(R.id.dock_battery_level_text); mAlarmStatus = (TextView) findViewById(R.id.alarm_status); mAlarmStatus.setOnClickListener(this); mSignalCluster = findViewById(R.id.signal_cluster); @@ -340,9 +341,26 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL } public void setBatteryController(BatteryController batteryController) { - mBatteryController = batteryController; - ((BatteryMeterView) findViewById(R.id.battery)).setBatteryController(batteryController); - mBatteryLevel.setBatteryController(batteryController); + BatteryMeterView v = ((BatteryMeterView) findViewById(R.id.battery)); + v.setBatteryStateRegistar(batteryController); + v.setBatteryController(batteryController); + mBatteryLevel.setBatteryStateRegistar(batteryController); + } + + public void setDockBatteryController(DockBatteryController dockBatteryController) { + DockBatteryMeterView v = ((DockBatteryMeterView) findViewById(R.id.dock_battery)); + if (dockBatteryController != null) { + v.setBatteryStateRegistar(dockBatteryController); + mDockBatteryLevel.setBatteryStateRegistar(dockBatteryController); + } else { + if (v != null) { + removeView(v); + } + if (mDockBatteryLevel != null) { + removeView(mDockBatteryLevel); + mDockBatteryLevel = null; + } + } } public void setNextAlarmController(NextAlarmController nextAlarmController) { @@ -414,6 +432,10 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL mEmergencyCallsOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly ? VISIBLE : GONE); mBatteryLevel.setForceShown(mExpanded && mShowBatteryTextExpanded); mBatteryLevel.setVisibility(View.VISIBLE); + if (mDockBatteryLevel != null) { + mDockBatteryLevel.setForceShown(mExpanded && mShowBatteryTextExpanded); + mDockBatteryLevel.setVisibility(View.VISIBLE); + } } private void updateSignalClusterDetachment() { @@ -763,6 +785,9 @@ public class StatusBarHeaderView extends RelativeLayout implements View.OnClickL applyAlpha(mDateCollapsed, values.dateCollapsedAlpha); applyAlpha(mDateExpanded, values.dateExpandedAlpha); applyAlpha(mBatteryLevel, values.batteryLevelAlpha); + if (mDockBatteryLevel != null) { + applyAlpha(mDockBatteryLevel, values.batteryLevelAlpha); + } applyAlpha(mSettingsContainer, values.settingsAlpha); applyAlpha(mWeatherLine1, values.settingsAlpha); applyAlpha(mWeatherLine2, values.settingsAlpha); 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 2347a33..19f2b09 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -114,23 +114,38 @@ public class StatusBarKeyguardViewManager { mShowing = true; mStatusBarWindowManager.setKeyguardShowing(true); mScrimController.abortKeyguardFadingOut(); - reset(); + reset(false); } /** * Shows the notification keyguard or the bouncer depending on * {@link KeyguardBouncer#needsFullscreenBouncer()}. */ - private void showBouncerOrKeyguard() { - if (mBouncer.needsFullscreenBouncer()) { - - // The keyguard might be showing (already). So we need to hide it. - mPhoneStatusBar.hideKeyguard(); - mBouncer.show(true /* resetSecuritySelection */); - } else { - mPhoneStatusBar.showKeyguard(); - mBouncer.hide(false /* destroyView */); - mBouncer.prepare(); + private void showBouncerOrKeyguard(boolean isBackPressed) { + switch (mBouncer.needsFullscreenBouncer()) { + case KeyguardBouncer.UNLOCK_SEQUENCE_FORCE_BOUNCER: + // SIM PIN/PUK + // The keyguard might be showing (already). So we need to hide it. + mPhoneStatusBar.hideKeyguard(); + mBouncer.show(true /* resetSecuritySelection */); + break; + case KeyguardBouncer.UNLOCK_SEQUENCE_BOUNCER_FIRST: + // Pattern/PIN/Password with "Directly pass to security view" enabled + if (isBackPressed) { + mPhoneStatusBar.showKeyguard(); + mBouncer.hide(false /* destroyView */); + mBouncer.prepare(); + } else { + // The keyguard might be showing (already). So we need to hide it. + mPhoneStatusBar.hideKeyguard(); + mBouncer.show(true /* resetSecuritySelection */); + } + break; + case KeyguardBouncer.UNLOCK_SEQUENCE_DEFAULT: + mPhoneStatusBar.showKeyguard(); + mBouncer.hide(false /* destroyView */); + mBouncer.prepare(); + break; } } @@ -157,14 +172,14 @@ public class StatusBarKeyguardViewManager { /** * Reset the state of the view. */ - public void reset() { + public void reset(boolean isBackPressed) { if (mShowing) { if (mOccluded) { mPhoneStatusBar.hideKeyguard(); mPhoneStatusBar.stopWaitingForKeyguardExit(); mBouncer.hide(false /* destroyView */); } else { - showBouncerOrKeyguard(); + showBouncerOrKeyguard(isBackPressed); } KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset(); updateStates(); @@ -233,7 +248,7 @@ public class StatusBarKeyguardViewManager { @Override public void run() { mStatusBarWindowManager.setKeyguardOccluded(mOccluded); - reset(); + reset(false); } }); return; @@ -245,7 +260,7 @@ public class StatusBarKeyguardViewManager { if (mUnlockFab != null && mUnlockFab.isAttachedToWindow() && !occluded) { hideUnlockFab(); } - reset(); + reset(false); } public boolean isOccluded() { @@ -372,6 +387,7 @@ public class StatusBarKeyguardViewManager { private void executeAfterKeyguardGoneAction() { if (mAfterKeyguardGoneAction != null) { + dismiss(); mAfterKeyguardGoneAction.onDismiss(); mAfterKeyguardGoneAction = null; } @@ -416,7 +432,7 @@ public class StatusBarKeyguardViewManager { public boolean onBackPressed() { if (mBouncer.isShowing()) { mPhoneStatusBar.endAffordanceLaunch(); - reset(); + reset(true); return true; } return false; @@ -449,7 +465,8 @@ public class StatusBarKeyguardViewManager { boolean showing = mShowing; boolean occluded = mOccluded; boolean bouncerShowing = mBouncer.isShowing(); - boolean bouncerDismissible = !mBouncer.isFullscreenBouncer(); + boolean bouncerDismissible = (mBouncer.isFullscreenBouncer() != + KeyguardBouncer.UNLOCK_SEQUENCE_FORCE_BOUNCER); if ((bouncerDismissible || !showing) != (mLastBouncerDismissible || !mLastShowing) || mFirstUpdate) { @@ -547,6 +564,10 @@ public class StatusBarKeyguardViewManager { public void animateCollapsePanels(float speedUpFactor) { mPhoneStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */, false /* delayed */, speedUpFactor); + if (mStatusBarWindowManager.keyguardExternalViewHasFocus()) { + mStatusBarWindowManager.setKeyguardExternalViewFocus(false); + dismiss(false); + } } /** 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 b5099e7..9a991f4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java @@ -35,6 +35,8 @@ import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.statusbar.BaseStatusBar; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.policy.KeyguardMonitor; +import cyanogenmod.providers.CMSettings; +import org.cyanogenmod.internal.util.CmLockPatternUtils; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -258,7 +260,8 @@ public class StatusBarWindowManager implements KeyguardMonitor.Callback { boolean isblur = false; if (mCurrentState.keyguardShowing && mKeyguardBlurEnabled && !mCurrentState.keyguardOccluded - && !mShowingMedia) { + && !mShowingMedia + && !isShowingLiveLockScreen()) { isblur = true; } if (mKeyguardBlur != null) { @@ -394,6 +397,13 @@ public class StatusBarWindowManager implements KeyguardMonitor.Callback { return mCurrentState.keyguardExternalViewHasFocus; } + private boolean isShowingLiveLockScreen() { + CmLockPatternUtils lockPatternUtils = new CmLockPatternUtils(mContext); + return (CMSettings.Secure.getInt(mContext.getContentResolver(), + CMSettings.Secure.LIVE_LOCK_SCREEN_ENABLED, 0) == 1) + && lockPatternUtils.isThirdPartyKeyguardEnabled(); + } + private static class State { boolean keyguardShowing; boolean keyguardOccluded; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java index a154544..c59a0d8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java @@ -34,7 +34,7 @@ import java.util.ArrayList; import cyanogenmod.providers.CMSettings; -public class BatteryController extends BroadcastReceiver { +public class BatteryController extends BroadcastReceiver implements BatteryStateRegistar { private static final String TAG = "BatteryController"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @@ -52,6 +52,7 @@ public class BatteryController extends BroadcastReceiver { private final PowerManager mPowerManager; private int mLevel; + private boolean mPresent; private boolean mPluggedIn; private boolean mCharging; private boolean mCharged; @@ -85,18 +86,21 @@ public class BatteryController extends BroadcastReceiver { public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("BatteryController state:"); pw.print(" mLevel="); pw.println(mLevel); + pw.print(" mPresent="); pw.println(mPresent); pw.print(" mPluggedIn="); pw.println(mPluggedIn); pw.print(" mCharging="); pw.println(mCharging); pw.print(" mCharged="); pw.println(mCharged); pw.print(" mPowerSave="); pw.println(mPowerSave); } + @Override public void addStateChangedCallback(BatteryStateChangeCallback cb) { mChangeCallbacks.add(cb); - cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging); + cb.onBatteryLevelChanged(mPresent, mLevel, mPluggedIn, mCharging); cb.onBatteryStyleChanged(mStyle, mPercentMode); } + @Override public void removeStateChangedCallback(BatteryStateChangeCallback cb) { mChangeCallbacks.remove(cb); } @@ -107,6 +111,7 @@ public class BatteryController extends BroadcastReceiver { mLevel = (int)(100f * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0) / intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100)); + mPresent = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false); mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0; final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, @@ -140,7 +145,7 @@ public class BatteryController extends BroadcastReceiver { private void fireBatteryLevelChanged() { final int N = mChangeCallbacks.size(); for (int i = 0; i < N; i++) { - mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging); + mChangeCallbacks.get(i).onBatteryLevelChanged(mPresent, mLevel, mPluggedIn, mCharging); } } @@ -158,12 +163,6 @@ public class BatteryController extends BroadcastReceiver { } } - public interface BatteryStateChangeCallback { - void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging); - void onPowerSaveChanged(); - void onBatteryStyleChanged(int style, int percentMode); - } - private final class SettingsObserver extends ContentObserver { private ContentResolver mResolver; private boolean mRegistered; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateRegistar.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateRegistar.java new file mode 100644 index 0000000..9fe9bb4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateRegistar.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy; + +public interface BatteryStateRegistar { + interface BatteryStateChangeCallback { + void onBatteryLevelChanged(boolean present, int level, boolean pluggedIn, boolean charging); + void onPowerSaveChanged(); + void onBatteryStyleChanged(int style, int percentMode); + } + + public void addStateChangedCallback(BatteryStateChangeCallback cb); + public void removeStateChangedCallback(BatteryStateChangeCallback cb); +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java index 4d3a49f..835c8ad 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java @@ -115,7 +115,7 @@ public class CastControllerImpl implements CastController { } if (mDiscovering) { mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaCallback, - MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY); + MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN); mCallbackRegistered = true; } else if (mCallbacks.size() != 0) { mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaCallback, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DockBatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DockBatteryController.java new file mode 100644 index 0000000..3faf7d0 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DockBatteryController.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2016 The CyanogenMod Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.policy; + +import android.content.BroadcastReceiver; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.BatteryManager; +import android.os.Handler; +import android.provider.Settings; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; + +import cyanogenmod.providers.CMSettings; + +public class DockBatteryController extends BroadcastReceiver implements BatteryStateRegistar { + + private final ArrayList<BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>(); + + private int mLevel; + private boolean mPresent; + private boolean mPluggedIn; + private boolean mCharging; + private boolean mCharged; + private boolean mPowerSave; + + private int mStyle; + private int mPercentMode; + private int mUserId; + private SettingsObserver mObserver; + + public DockBatteryController(Context context, Handler handler) { + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_BATTERY_CHANGED); + context.registerReceiver(this, filter); + + mObserver = new SettingsObserver(context, handler); + mObserver.observe(); + } + + public void setUserId(int userId) { + mUserId = userId; + mObserver.observe(); + } + + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("BatteryController state:"); + pw.print(" mLevel="); pw.println(mLevel); + pw.print(" mPresent="); pw.println(mPresent); + pw.print(" mPluggedIn="); pw.println(mPluggedIn); + pw.print(" mCharging="); pw.println(mCharging); + pw.print(" mCharged="); pw.println(mCharged); + pw.print(" mPowerSave="); pw.println(mPowerSave); + } + + @Override + public void addStateChangedCallback(BatteryStateChangeCallback cb) { + mChangeCallbacks.add(cb); + cb.onBatteryLevelChanged(mPresent, mLevel, mPluggedIn, mCharging); + cb.onBatteryStyleChanged(mStyle, mPercentMode); + } + + @Override + public void removeStateChangedCallback(BatteryStateChangeCallback cb) { + mChangeCallbacks.remove(cb); + } + + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { + mLevel = (int)(100f + * intent.getIntExtra(BatteryManager.EXTRA_DOCK_LEVEL, 0) + / intent.getIntExtra(BatteryManager.EXTRA_DOCK_SCALE, 100)); + mPresent = intent.getBooleanExtra(BatteryManager.EXTRA_DOCK_PRESENT, false); + mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_DOCK_PLUGGED, 0) != 0; + + final int status = intent.getIntExtra(BatteryManager.EXTRA_DOCK_STATUS, + BatteryManager.BATTERY_STATUS_UNKNOWN); + mCharged = status == BatteryManager.BATTERY_STATUS_FULL; + mCharging = mPluggedIn && (mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING); + + fireBatteryLevelChanged(); + } + } + + private void fireBatteryLevelChanged() { + final int N = mChangeCallbacks.size(); + for (int i = 0; i < N; i++) { + mChangeCallbacks.get(i).onBatteryLevelChanged(mPresent, mLevel, mPresent, mCharging); + } + } + + private void fireSettingsChanged() { + final int N = mChangeCallbacks.size(); + for (int i = 0; i < N; i++) { + mChangeCallbacks.get(i).onBatteryStyleChanged(mStyle, mPercentMode); + } + } + + private final class SettingsObserver extends ContentObserver { + private ContentResolver mResolver; + private boolean mRegistered; + + private final Uri STYLE_URI = + CMSettings.System.getUriFor(CMSettings.System.STATUS_BAR_BATTERY_STYLE); + private final Uri PERCENT_URI = + CMSettings.System.getUriFor(CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT); + + public SettingsObserver(Context context, Handler handler) { + super(handler); + mResolver = context.getContentResolver(); + } + + public void observe() { + if (mRegistered) { + mResolver.unregisterContentObserver(this); + } + mResolver.registerContentObserver(STYLE_URI, false, this, mUserId); + mResolver.registerContentObserver(PERCENT_URI, false, this, mUserId); + mRegistered = true; + + update(); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + update(); + } + + private void update() { + mStyle = CMSettings.System.getIntForUser(mResolver, + CMSettings.System.STATUS_BAR_BATTERY_STYLE, 0, mUserId); + mPercentMode = CMSettings.System.getIntForUser(mResolver, + CMSettings.System.STATUS_BAR_SHOW_BATTERY_PERCENT, 0, mUserId); + + fireSettingsChanged(); + } + }; +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java index 2e348e6..52a2825 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightController.java @@ -29,6 +29,8 @@ import android.hardware.camera2.CameraManager; import android.os.Handler; import android.os.HandlerThread; import android.os.Process; +import android.os.PowerManager; +import android.os.PowerManager.WakeLock; import android.text.TextUtils; import android.util.Log; @@ -49,6 +51,8 @@ public class FlashlightController { private static final int DISPATCH_CHANGED = 1; private static final int DISPATCH_AVAILABILITY_CHANGED = 2; + private static boolean mUseWakeLock; + private static final String ACTION_TURN_FLASHLIGHT_OFF = "com.android.systemui.action.TURN_FLASHLIGHT_OFF"; @@ -66,6 +70,8 @@ public class FlashlightController { private final String mCameraId; private boolean mTorchAvailable; + private WakeLock mWakeLock; + private Notification mNotification = null; private boolean mReceiverRegistered; private BroadcastReceiver mReceiver = new BroadcastReceiver() { @@ -98,6 +104,11 @@ public class FlashlightController { mCameraId = cameraId; } + mUseWakeLock = mContext.getResources().getBoolean(R.bool.flashlight_use_wakelock); + + PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); + if (mCameraId != null) { ensureHandler(); mCameraManager.registerTorchCallback(mTorchCallback, mHandler); @@ -109,12 +120,25 @@ public class FlashlightController { synchronized (this) { if (mFlashlightEnabled != enabled) { mFlashlightEnabled = enabled; + + if (mUseWakeLock) { + if (enabled) { + if (!mWakeLock.isHeld()) mWakeLock.acquire(); + } else { + if (mWakeLock.isHeld()) mWakeLock.release(); + } + } + try { mCameraManager.setTorchMode(mCameraId, enabled); } catch (CameraAccessException e) { Log.e(TAG, "Couldn't set torch mode", e); mFlashlightEnabled = false; pendingError = true; + + if (mUseWakeLock && mWakeLock.isHeld()) { + mWakeLock.release(); + } } } } @@ -287,6 +311,11 @@ public class FlashlightController { synchronized (FlashlightController.this) { changed = mTorchAvailable != available; mTorchAvailable = available; + + if (mUseWakeLock && !available) { + if (mWakeLock.isHeld()) + mWakeLock.release(); + } } if (changed) { if (DEBUG) Log.d(TAG, "dispatchAvailabilityChanged(" + available + ")"); @@ -299,6 +328,11 @@ public class FlashlightController { synchronized (FlashlightController.this) { changed = mFlashlightEnabled != enabled; mFlashlightEnabled = enabled; + + if (mUseWakeLock && !enabled) { + if (mWakeLock.isHeld()) + mWakeLock.release(); + } } if (changed) { if (DEBUG) Log.d(TAG, "dispatchModeChanged(" + enabled + ")"); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java index 5847f42..3d1212b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java @@ -457,7 +457,10 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL mReleaseOnExpandFinish = false; } else { for (NotificationData.Entry entry : mEntriesToRemoveAfterExpand) { - removeHeadsUpEntry(entry); + if (isHeadsUp(entry.key)) { + // Maybe the heads-up was removed already + removeHeadsUpEntry(entry); + } } } mEntriesToRemoveAfterExpand.clear(); @@ -576,6 +579,9 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL earliestRemovaltime = currentTime + mMinimumDisplayTime; postTime = Math.max(postTime, currentTime); removeAutoRemovalCallbacks(); + if (mEntriesToRemoveAfterExpand.contains(entry)) { + mEntriesToRemoveAfterExpand.remove(entry); + } if (!hasFullScreenIntent(entry)) { long finishTime = postTime + mHeadsUpNotificationDecay; long removeDelay = Math.max(finishTime - currentTime, mMinimumDisplayTime); 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 435787e..a8e977f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -397,10 +397,10 @@ public class MobileSignalController extends SignalController< mCurrentState.dataConnected = mCurrentState.connected && mDataState == TelephonyManager.DATA_CONNECTED; + mCurrentState.showSeparateRoaming = false; if (isCarrierNetworkChangeActive()) { mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE; } else if (isRoaming()) { - mCurrentState.showSeparateRoaming = false; if (SystemProperties.getBoolean("ro.config.always_show_roaming", false)) { mCurrentState.showSeparateRoaming = true; } else { @@ -476,6 +476,7 @@ public class MobileSignalController extends SignalController< + " dataState=" + state.getDataRegState()); } mServiceState = state; + mDataNetType = state.getDataNetworkType(); updateTelephony(); } 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 4ec8b43..2f04b42 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -211,8 +211,6 @@ public class NotificationStackScrollLayout extends ViewGroup private boolean mDisallowScrollingInThisMotion; private long mGoToFullShadeDelay; - private final PerformanceManager mPerf; - private ViewTreeObserver.OnPreDrawListener mChildrenUpdater = new ViewTreeObserver.OnPreDrawListener() { @Override @@ -259,8 +257,6 @@ public class NotificationStackScrollLayout extends ViewGroup mExpandHelper.setEventSource(this); mExpandHelper.setScrollAdapter(this); - mPerf = PerformanceManager.getInstance(context); - mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, getContext()); mSwipeHelper.setLongPressListener(mLongPressListener); initView(context); @@ -847,10 +843,6 @@ public class NotificationStackScrollLayout extends ViewGroup horizontalSwipeWantsIt = mSwipeHelper.onTouchEvent(ev); } - if (expandWantsIt && mIsBeingDragged) { - mPerf.cpuBoost(200 * 1000); - } - return horizontalSwipeWantsIt || scrollerWantsIt || expandWantsIt || super.onTouchEvent(ev); } diff --git a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java index a2b062c..0ae34bf 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java @@ -155,7 +155,7 @@ public class DemoModeFragment extends PreferenceFragment implements OnPreference getContext().sendBroadcast(intent); intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_CLOCK); - intent.putExtra("hhmm", "0600"); + intent.putExtra("hhmm", "1230"); getContext().sendBroadcast(intent); intent.putExtra(DemoMode.EXTRA_COMMAND, DemoMode.COMMAND_NETWORK); diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java index 3ed18c9..27c6601 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java @@ -130,6 +130,7 @@ public class VolumeDialog { private boolean mPendingStateChanged; private boolean mPendingRecheckAll; private long mCollapseTime; + private int mLastActiveStream; public VolumeDialog(Context context, int windowType, VolumeDialogController controller, ZenModeController zenModeController, Callback callback) { @@ -194,7 +195,7 @@ public class VolumeDialog { }); addRow(AudioManager.STREAM_RING, - R.drawable.ic_ringer_audible, R.drawable.ic_volume_ringer_mute, true); + R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true); addRow(AudioManager.STREAM_MUSIC, R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true); addRow(AudioManager.STREAM_ALARM, @@ -275,10 +276,14 @@ public class VolumeDialog { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - final boolean moved = oldLeft != left || oldTop != top; + final boolean moved = mLastActiveStream != mActiveStream || + oldLeft != left || oldTop != top; if (D.BUG) Log.d(TAG, "onLayoutChange moved=" + moved + " old=" + new Rect(oldLeft, oldTop, oldRight, oldBottom).toShortString() - + " new=" + new Rect(left,top,right,bottom).toShortString()); + + "," + mLastActiveStream + + " new=" + new Rect(left,top,right,bottom).toShortString() + + "," + mActiveStream); + mLastActiveStream = mActiveStream; if (moved) { for (int i = 0; i < mDialogContentView.getChildCount(); i++) { final View c = mDialogContentView.getChildAt(i); @@ -652,9 +657,9 @@ public class VolumeDialog { removeRow(notificationRow); } } else if (!mState.linkedNotification) { - // TODO get icon for mute state addRow(AudioManager.STREAM_NOTIFICATION, - R.drawable.ic_notification_audible, R.drawable.ic_notification_audible, true); + R.drawable.ic_volume_notification, R.drawable.ic_volume_notification_mute, + true); } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java index 024fb8c..9494e27 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogController.java @@ -29,6 +29,7 @@ import android.database.ContentObserver; import android.media.AudioManager; import android.media.AudioSystem; import android.media.IVolumeController; +import android.media.ToneGenerator; import android.media.VolumePolicy; import android.media.session.MediaController.PlaybackInfo; import android.media.session.MediaSession.Token; @@ -54,6 +55,8 @@ import java.util.HashMap; import java.util.Map; import java.util.Objects; +import cyanogenmod.providers.CMSettings; + /** * Source of truth for all state / events related to the volume dialog. No presentation. * @@ -67,6 +70,9 @@ public class VolumeDialogController { private static final int DYNAMIC_STREAM_START_INDEX = 100; private static final int VIBRATE_HINT_DURATION = 50; + private static final int FREE_DELAY = 10000; + private static final int BEEP_DURATION = 150; + private static final int[] STREAMS = { AudioSystem.STREAM_ALARM, AudioSystem.STREAM_BLUETOOTH_SCO, @@ -102,10 +108,13 @@ public class VolumeDialogController { private VolumePolicy mVolumePolicy; private boolean mShowDndTile = true; + private ToneGenerator mToneGenerators[]; + public VolumeDialogController(Context context, ComponentName component) { mContext = context.getApplicationContext(); Events.writeEvent(mContext, Events.EVENT_COLLECTION_STARTED); mComponent = component; + mToneGenerators = new ToneGenerator[AudioSystem.getNumStreamTypes()]; mWorkerThread = new HandlerThread(VolumeDialogController.class.getSimpleName()); mWorkerThread.start(); mWorker = new W(mWorkerThread.getLooper()); @@ -289,6 +298,7 @@ public class VolumeDialogController { final boolean fromKey = (flags & AudioManager.FLAG_FROM_KEY) != 0; final boolean showVibrateHint = (flags & AudioManager.FLAG_SHOW_VIBRATE_HINT) != 0; final boolean showSilentHint = (flags & AudioManager.FLAG_SHOW_SILENT_HINT) != 0; + final boolean playSound = (flags & AudioManager.FLAG_PLAY_SOUND) != 0; boolean changed = false; if (showUI) { changed |= updateActiveStreamW(stream); @@ -308,6 +318,19 @@ public class VolumeDialogController { if (showSilentHint) { mCallbacks.onShowSilentHint(); } + if (playSound) { + if ((flags & AudioManager.FLAG_PLAY_SOUND) != 0) { + mWorker.removeMessages(W.PLAY_SOUND); + mWorker.sendMessageDelayed(mWorker.obtainMessage(W.PLAY_SOUND, stream, flags), + AudioSystem.PLAY_SOUND_DELAY); + } + + if ((flags & AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE) != 0) { + mWorker.removeMessages(W.PLAY_SOUND); + onStopSoundsW(); + } + + } if (changed && fromKey) { Events.writeEvent(mContext, Events.EVENT_KEY, stream, lastAudibleStreamVolume); } @@ -566,6 +589,9 @@ public class VolumeDialogController { private static final int NOTIFY_VISIBLE = 12; private static final int USER_ACTIVITY = 13; private static final int SHOW_SAFETY_WARNING = 14; + private static final int PLAY_SOUND = 15; + private static final int STOP_SOUNDS = 16; + private static final int FREE_RESOURCES = 17; W(Looper looper) { super(looper); @@ -588,6 +614,9 @@ public class VolumeDialogController { case NOTIFY_VISIBLE: onNotifyVisibleW(msg.arg1 != 0); break; case USER_ACTIVITY: onUserActivityW(); break; case SHOW_SAFETY_WARNING: onShowSafetyWarningW(msg.arg1); break; + case PLAY_SOUND: onPlaySoundW(msg.arg1, msg.arg2); break; + case STOP_SOUNDS: onStopSoundsW(); break; + case FREE_RESOURCES: onFreeResourcesW(); break; } } } @@ -717,6 +746,66 @@ public class VolumeDialogController { } + protected void onPlaySoundW(int streamType, int flags) { + + // If preference is no sound - just exit here + if (CMSettings.System.getInt(mContext.getContentResolver(), + CMSettings.System.VOLUME_ADJUST_SOUNDS_ENABLED, 1) == 0) { + return; + } + + if (mWorker.hasMessages(W.STOP_SOUNDS)) { + mWorker.removeMessages(W.STOP_SOUNDS); + // Force stop right now + onStopSoundsW(); + } + + ToneGenerator toneGen = getOrCreateToneGeneratorW(streamType); + if (toneGen != null) { + toneGen.startTone(ToneGenerator.TONE_PROP_BEEP); + mWorker.sendMessageDelayed(mWorker.obtainMessage(W.STOP_SOUNDS), BEEP_DURATION); + } + + mWorker.removeMessages(W.FREE_RESOURCES); + mWorker.sendMessageDelayed(mWorker.obtainMessage(W.FREE_RESOURCES), FREE_DELAY); + } + + protected void onStopSoundsW() { + int numStreamTypes = AudioSystem.getNumStreamTypes(); + for (int i = numStreamTypes - 1; i >= 0; i--) { + ToneGenerator toneGen = mToneGenerators[i]; + if (toneGen != null) { + toneGen.stopTone(); + } + } + } + + private ToneGenerator getOrCreateToneGeneratorW(int streamType) { + if (mToneGenerators[streamType] == null) { + try { + mToneGenerators[streamType] = new ToneGenerator(streamType, + ToneGenerator.MAX_VOLUME); + } catch (RuntimeException e) { + if (false) { + Log.d(TAG, "ToneGenerator constructor failed with " + + "RuntimeException: " + e); + } + } + } + return mToneGenerators[streamType]; + } + + protected void onFreeResourcesW() { + synchronized (this) { + for (int i = mToneGenerators.length - 1; i >= 0; i--) { + if (mToneGenerators[i] != null) { + mToneGenerators[i].release(); + } + mToneGenerators[i] = null; + } + } + } + private final class SettingObserver extends ContentObserver { private final Uri SERVICE_URI = Settings.Secure.getUriFor( Settings.Secure.VOLUME_CONTROLLER_SERVICE_COMPONENT); @@ -885,6 +974,13 @@ public class VolumeDialogController { @Override public void onRemoteVolumeChanged(Token token, int flags) { + // If an inactive session changed the remoteVolume, bail + // since we don't have any active streams to update + if (!mRemoteStreams.containsKey(token)) { + Log.i(TAG, "onRemoteVolumeChanged called on inactive" + + "stream. Ignoring"); + return; + } final int stream = mRemoteStreams.get(token); final boolean showUI = (flags & AudioManager.FLAG_SHOW_UI) != 0; boolean changed = updateActiveStreamW(stream); diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java index 07ec843..ddf623a 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java +++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java @@ -70,9 +70,7 @@ public class ZenModePanel extends LinearLayout { private static final int SECONDS_MS = 1000; private static final int MINUTES_MS = 60 * SECONDS_MS; - private static final int[] MINUTE_BUCKETS = DEBUG - ? new int[] { 0, 1, 2, 5, 15, 30, 45, 60, 120, 180, 240, 480 } - : ZenModeConfig.MINUTE_BUCKETS; + private static final int[] MINUTE_BUCKETS = ZenModeConfig.MINUTE_BUCKETS; private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0]; private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1]; private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60); @@ -421,8 +419,13 @@ public class ZenModePanel extends LinearLayout { mZenIntroductionCustomize.setVisibility(zenImportant ? VISIBLE : GONE); } final String warning = computeAlarmWarningText(zenNone); - mZenAlarmWarning.setVisibility(warning != null ? VISIBLE : GONE); + final int oldVis = mZenAlarmWarning.getVisibility(); + final int newVis = warning != null ? VISIBLE : GONE; + mZenAlarmWarning.setVisibility(newVis); mZenAlarmWarning.setText(warning); + if (newVis != oldVis) { + requestLayout(); + } } private String computeAlarmWarningText(boolean zenNone) { @@ -603,13 +606,6 @@ public class ZenModePanel extends LinearLayout { if (DEBUG) Log.d(mTag, "bind i=" + mZenConditions.indexOfChild(row) + " first=" + first + " condition=" + conditionId); tag.rb.setEnabled(enabled); - final boolean checked = (mSessionExitCondition != null - || mAttachedZen != Global.ZEN_MODE_OFF) - && (sameConditionId(mSessionExitCondition, tag.condition)); - if (checked != tag.rb.isChecked()) { - if (DEBUG) Log.d(mTag, "bind checked=" + checked + " condition=" + conditionId); - tag.rb.setChecked(checked); - } tag.rb.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { |