diff options
21 files changed, 381 insertions, 103 deletions
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 0ea5200d202a..1784d8ad3c6c 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -8447,6 +8447,20 @@ public class PackageParser { // Collect certificates if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) { collectCertificates(p, apexFile, false); + // Keep legacy mechanism for handling signatures. While this is deprecated, it's + // still part of the public API and needs to be maintained + if (p.mSigningDetails.hasPastSigningCertificates()) { + // Package has included signing certificate rotation information. Return + // the oldest cert so that programmatic checks keep working even if unaware + // of key rotation. + pi.signatures = new Signature[1]; + pi.signatures[0] = p.mSigningDetails.pastSigningCertificates[0]; + } else if (p.mSigningDetails.hasSignatures()) { + // otherwise keep old behavior + int numberOfSigs = p.mSigningDetails.signatures.length; + pi.signatures = new Signature[numberOfSigs]; + System.arraycopy(p.mSigningDetails.signatures, 0, pi.signatures, 0, numberOfSigs); + } if (p.mSigningDetails != SigningDetails.UNKNOWN) { // only return a valid SigningInfo if there is signing information to report pi.signingInfo = new SigningInfo(p.mSigningDetails); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 83dc39e94d7a..ac59101d4090 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -12666,6 +12666,45 @@ public final class Settings { public static final String DYNAMIC_POWER_SAVINGS_ENABLED = "dynamic_power_savings_enabled"; /** + * A long value indicating how much longer the system battery is estimated to last in + * millis. See {@link #BATTERY_ESTIMATES_LAST_UPDATE_TIME} for the last time this value + * was updated. + * + * @hide + */ + public static final String TIME_REMAINING_ESTIMATE_MILLIS = + "time_remaining_estimate_millis"; + + /** + * A boolean indicating whether {@link #TIME_REMAINING_ESTIMATE_MILLIS} is based customized + * to the devices usage or using global models. See + * {@link #BATTERY_ESTIMATES_LAST_UPDATE_TIME} for the last time this value was updated. + * + * @hide + */ + public static final String TIME_REMAINING_ESTIMATE_BASED_ON_USAGE = + "time_remaining_estimate_based_on_usage"; + + /** + * A long value indicating how long the system battery takes to deplete from 100% to 0% on + * average based on historical drain rates. See {@link #BATTERY_ESTIMATES_LAST_UPDATE_TIME} + * for the last time this value was updated. + * + * @hide + */ + public static final String AVERAGE_TIME_TO_DISCHARGE = "average_time_to_discharge"; + + /** + * A long indicating the epoch time in milliseconds when + * {@link #TIME_REMAINING_ESTIMATE_MILLIS}, {@link #TIME_REMAINING_ESTIMATE_BASED_ON_USAGE}, + * and {@link #AVERAGE_TIME_TO_DISCHARGE} were last updated. + * + * @hide + */ + public static final String BATTERY_ESTIMATES_LAST_UPDATE_TIME = + "battery_estimates_last_update_time"; + + /** * The max value for {@link #LOW_POWER_MODE_TRIGGER_LEVEL}. If this setting is not set * or the value is 0, the default max will be used. * @@ -13531,6 +13570,28 @@ public final class Settings { private static final Validator AWARE_ALLOWED_VALIDATOR = BOOLEAN_VALIDATOR; /** + * Overrides internal R.integer.config_longPressOnPowerBehavior. + * Allowable values detailed in frameworks/base/core/res/res/values/config.xml. + * Used by PhoneWindowManager. + * @hide + */ + public static final String POWER_BUTTON_LONG_PRESS = + "power_button_long_press"; + private static final Validator POWER_BUTTON_LONG_PRESS_VALIDATOR = + new SettingsValidators.InclusiveIntegerRangeValidator(0, 5); + + /** + * Overrides internal R.integer.config_veryLongPressOnPowerBehavior. + * Allowable values detailed in frameworks/base/core/res/res/values/config.xml. + * Used by PhoneWindowManager. + * @hide + */ + public static final String POWER_BUTTON_VERY_LONG_PRESS = + "power_button_very_long_press"; + private static final Validator POWER_BUTTON_VERY_LONG_PRESS_VALIDATOR = + new SettingsValidators.InclusiveIntegerRangeValidator(0, 1); + + /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. * @@ -13643,6 +13704,8 @@ public final class Settings { WIFI_PNO_RECENCY_SORTING_ENABLED_VALIDATOR); VALIDATORS.put(WIFI_LINK_PROBING_ENABLED, WIFI_LINK_PROBING_ENABLED_VALIDATOR); VALIDATORS.put(AWARE_ALLOWED, AWARE_ALLOWED_VALIDATOR); + VALIDATORS.put(POWER_BUTTON_LONG_PRESS, POWER_BUTTON_LONG_PRESS_VALIDATOR); + VALIDATORS.put(POWER_BUTTON_VERY_LONG_PRESS, POWER_BUTTON_VERY_LONG_PRESS_VALIDATOR); } /** @@ -14648,6 +14711,7 @@ public final class Settings { */ public static final String TEXT_CLASSIFIER_ACTION_MODEL_PARAMS = "text_classifier_action_model_params"; + } /** diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 9c4717b4497e..b3e94e39f30e 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1098,6 +1098,7 @@ 2 - Power off (with confirmation) 3 - Power off (without confirmation) 4 - Go to voice assist + 5 - Go to assistant (Settings.Secure.ASSISTANT) --> <integer name="config_longPressOnPowerBehavior">1</integer> diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 0e94abc0dcac..a853121bac4e 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -130,8 +130,10 @@ public class SettingsBackupTest { Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE, Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, Settings.Global.AUTOMATIC_POWER_SAVE_MODE, + Settings.Global.AVERAGE_TIME_TO_DISCHARGE, Settings.Global.BACKGROUND_ACTIVITY_STARTS_ENABLED, Settings.Global.BATTERY_CHARGING_STATE_UPDATE_DELAY, + Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME, Settings.Global.BROADCAST_BG_CONSTANTS, Settings.Global.BROADCAST_FG_CONSTANTS, Settings.Global.BROADCAST_OFFLOAD_CONSTANTS, @@ -462,6 +464,8 @@ public class SettingsBackupTest { Settings.Global.TEXT_CLASSIFIER_ACTION_MODEL_PARAMS, Settings.Global.THEATER_MODE_ON, Settings.Global.TIME_ONLY_MODE_CONSTANTS, + Settings.Global.TIME_REMAINING_ESTIMATE_MILLIS, + Settings.Global.TIME_REMAINING_ESTIMATE_BASED_ON_USAGE, Settings.Global.TRANSITION_ANIMATION_SCALE, Settings.Global.TRUSTED_SOUND, Settings.Global.TZINFO_UPDATE_CONTENT_URL, @@ -573,7 +577,10 @@ public class SettingsBackupTest { Settings.Global.RADIO_BUG_WAKELOCK_TIMEOUT_COUNT_THRESHOLD, Settings.Global.RADIO_BUG_SYSTEM_ERROR_COUNT_THRESHOLD, Settings.Global.ENABLED_SUBSCRIPTION_FOR_SLOT, - Settings.Global.MODEM_STACK_ENABLED_FOR_SLOT); + Settings.Global.MODEM_STACK_ENABLED_FOR_SLOT, + Settings.Global.POWER_BUTTON_LONG_PRESS, + Settings.Global.POWER_BUTTON_VERY_LONG_PRESS); + private static final Set<String> BACKUP_BLACKLISTED_SECURE_SETTINGS = newHashSet( Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE, diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java index fb5c16b92930..e19ac815b939 100644 --- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java @@ -37,7 +37,8 @@ public class BatterySaverUtils { /** * When set to "true" the notification will be a generic confirm message instead of asking the * user if they want to turn on battery saver. If set to false the dialog will specifically - * talk about turning on battery saver and provide a button for taking the action. + * talk about battery saver without giving the option of turning it on. The only button visible + * will be a generic confirmation button to acknowledge the dialog. */ public static final String EXTRA_CONFIRM_TEXT_ONLY = "extra_confirm_only"; /** diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/Estimate.kt b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/Estimate.kt new file mode 100644 index 000000000000..ae8e1e2a60c0 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/Estimate.kt @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.settingslib.fuelgauge + +import android.content.Context +import android.provider.Settings +import java.time.Duration +import java.time.Instant + +const val AVERAGE_TIME_TO_DISCHARGE_UNKNOWN = -1 +const val ESTIMATE_MILLIS_UNKNOWN = -1 + +class Estimate( + val estimateMillis: Long, + val isBasedOnUsage: Boolean, + val averageDischargeTime: Long +) { + companion object { + /** + * Returns the cached estimate if it is available and fresh. Will return null if estimate is + * unavailable or older than 2 minutes. + * + * @param context A valid context + * @return An [Estimate] object with the latest battery estimates. + */ + @JvmStatic + fun getCachedEstimateIfAvailable(context: Context): Estimate? { + // if time > 2 min return null or the estimate otherwise + val resolver = context.contentResolver + val lastUpdateTime = Instant.ofEpochMilli( + Settings.Global.getLong( + resolver, Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME, -1)) + return if (Duration.between(lastUpdateTime, + Instant.now()).compareTo(Duration.ofMinutes(2)) > 0) { + null + } else Estimate( + Settings.Global.getLong(resolver, + Settings.Global.TIME_REMAINING_ESTIMATE_MILLIS, + ESTIMATE_MILLIS_UNKNOWN.toLong()), + Settings.Global.getInt(resolver, + Settings.Global.TIME_REMAINING_ESTIMATE_BASED_ON_USAGE, 0) == 1, + Settings.Global.getLong(resolver, Settings.Global.AVERAGE_TIME_TO_DISCHARGE, + AVERAGE_TIME_TO_DISCHARGE_UNKNOWN.toLong())) + } + + /** + * Stores an estimate to the cache along with a timestamp. Can be obtained via + * [.getCachedEstimateIfAvailable]. + * + * @param context A valid context + * @param estimate the [Estimate] object to store + */ + @JvmStatic + fun storeCachedEstimate(context: Context, estimate: Estimate) { + // store the estimate and update the timestamp + val resolver = context.contentResolver + Settings.Global.putLong(resolver, Settings.Global.TIME_REMAINING_ESTIMATE_MILLIS, + estimate.estimateMillis) + Settings.Global.putInt(resolver, Settings.Global.TIME_REMAINING_ESTIMATE_BASED_ON_USAGE, + if (estimate.isBasedOnUsage) 1 else 0) + Settings.Global.putLong(resolver, Settings.Global.AVERAGE_TIME_TO_DISCHARGE, + estimate.averageDischargeTime) + Settings.Global.putLong(resolver, Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME, + System.currentTimeMillis()) + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 9d9c88f2c6ca..744f88d19ba3 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -86,7 +86,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi @Retention(SOURCE) @IntDef({DISMISS_USER_GESTURE, DISMISS_AGED, DISMISS_TASK_FINISHED, DISMISS_BLOCKED, - DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION}) + DISMISS_NOTIF_CANCEL, DISMISS_ACCESSIBILITY_ACTION, DISMISS_NO_LONGER_BUBBLE}) @interface DismissReason {} static final int DISMISS_USER_GESTURE = 1; @@ -95,6 +95,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi static final int DISMISS_BLOCKED = 4; static final int DISMISS_NOTIF_CANCEL = 5; static final int DISMISS_ACCESSIBILITY_ACTION = 6; + static final int DISMISS_NO_LONGER_BUBBLE = 7; static final int MAX_BUBBLES = 5; // TODO: actually enforce this @@ -129,8 +130,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private final StatusBarWindowController mStatusBarWindowController; private StatusBarStateListener mStatusBarStateListener; - private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider = - Dependency.get(NotificationInterruptionStateProvider.class); + private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider; private INotificationManager mNotificationManagerService; @@ -189,15 +189,19 @@ public class BubbleController implements ConfigurationController.ConfigurationLi @Inject public BubbleController(Context context, StatusBarWindowController statusBarWindowController, - BubbleData data, ConfigurationController configurationController) { + BubbleData data, ConfigurationController configurationController, + NotificationInterruptionStateProvider interruptionStateProvider) { this(context, statusBarWindowController, data, null /* synchronizer */, - configurationController); + configurationController, interruptionStateProvider); } public BubbleController(Context context, StatusBarWindowController statusBarWindowController, BubbleData data, @Nullable BubbleStackView.SurfaceSynchronizer synchronizer, - ConfigurationController configurationController) { + ConfigurationController configurationController, + NotificationInterruptionStateProvider interruptionStateProvider) { mContext = context; + mNotificationInterruptionStateProvider = interruptionStateProvider; + configurationController.addCallback(this /* configurationListener */); mNotificationEntryManager = Dependency.get(NotificationEntryManager.class); @@ -394,7 +398,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (!areBubblesEnabled(mContext)) { return; } - if (shouldAutoBubbleForFlags(mContext, entry) || shouldBubble(entry)) { + if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) { // TODO: handle group summaries? updateShowInShadeForSuppressNotification(entry); } @@ -405,7 +409,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (!areBubblesEnabled(mContext)) { return; } - if (entry.isBubble() && mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) { + if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry)) { updateBubble(entry); } } @@ -415,8 +419,11 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (!areBubblesEnabled(mContext)) { return; } - if (mNotificationInterruptionStateProvider.shouldBubbleUp(entry) - && alertAgain(entry, entry.notification.getNotification())) { + boolean shouldBubble = mNotificationInterruptionStateProvider.shouldBubbleUp(entry); + if (!shouldBubble && mBubbleData.hasBubbleWithKey(entry.key)) { + // It was previously a bubble but no longer a bubble -- lets remove it + removeBubble(entry.key, DISMISS_NO_LONGER_BUBBLE); + } else if (shouldBubble && alertAgain(entry, entry.notification.getNotification())) { updateShowInShadeForSuppressNotification(entry); entry.setBubbleDismissed(false); // updates come back as bubbles even if dismissed updateBubble(entry); @@ -561,17 +568,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi } /** - * Whether the notification has been developer configured to bubble and is allowed by the user. - */ - @VisibleForTesting - protected boolean shouldBubble(NotificationEntry entry) { - StatusBarNotification n = entry.notification; - boolean hasOverlayIntent = n.getNotification().getBubbleMetadata() != null - && n.getNotification().getBubbleMetadata().getIntent() != null; - return hasOverlayIntent && entry.canBubble; - } - - /** * Whether the notification should automatically bubble or not. Gated by secure settings flags. */ @VisibleForTesting diff --git a/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt b/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt index 02ad0f1766bd..f73bc93ff313 100644 --- a/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt +++ b/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt @@ -15,6 +15,7 @@ data class BatteryStateSnapshot( val severeLevelThreshold: Int, val lowLevelThreshold: Int, val timeRemainingMillis: Long, + val averageTimeToDischargeMillis: Long, val severeThresholdMillis: Long, val lowThresholdMillis: Long, val isBasedOnUsage: Boolean, @@ -39,18 +40,19 @@ data class BatteryStateSnapshot( severeLevelThreshold: Int, lowLevelThreshold: Int ) : this( - batteryLevel, - isPowerSaver, - plugged, - bucket, - batteryStatus, - severeLevelThreshold, - lowLevelThreshold, - NO_ESTIMATE_AVAILABLE.toLong(), - NO_ESTIMATE_AVAILABLE.toLong(), - NO_ESTIMATE_AVAILABLE.toLong(), - false, - true + batteryLevel, + isPowerSaver, + plugged, + bucket, + batteryStatus, + severeLevelThreshold, + lowLevelThreshold, + NO_ESTIMATE_AVAILABLE.toLong(), + NO_ESTIMATE_AVAILABLE.toLong(), + NO_ESTIMATE_AVAILABLE.toLong(), + NO_ESTIMATE_AVAILABLE.toLong(), + false, + true ) { this.isHybrid = false } diff --git a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java index a87922792616..3b464783d009 100644 --- a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java +++ b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java @@ -1,5 +1,7 @@ package com.android.systemui.power; +import com.android.settingslib.fuelgauge.Estimate; + public interface EnhancedEstimates { /** diff --git a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java index bfb809ecbf34..9b1f23aa0d0c 100644 --- a/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java @@ -1,5 +1,7 @@ package com.android.systemui.power; +import com.android.settingslib.fuelgauge.Estimate; + public class EnhancedEstimatesImpl implements EnhancedEstimates { @Override diff --git a/packages/SystemUI/src/com/android/systemui/power/Estimate.kt b/packages/SystemUI/src/com/android/systemui/power/Estimate.kt deleted file mode 100644 index dca0d45c1c9f..000000000000 --- a/packages/SystemUI/src/com/android/systemui/power/Estimate.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.android.systemui.power - -data class Estimate(val estimateMillis: Long, val isBasedOnUsage: Boolean)
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java index 25d6d940d92e..b57c053964ca 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java @@ -42,6 +42,7 @@ import android.util.Log; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; +import com.android.settingslib.fuelgauge.Estimate; import com.android.settingslib.utils.ThreadUtils; import com.android.systemui.Dependency; import com.android.systemui.R; @@ -283,6 +284,7 @@ public class PowerUI extends SystemUI { mCurrentBatteryStateSnapshot = new BatteryStateSnapshot(mBatteryLevel, isPowerSaverMode, plugged, bucket, mBatteryStatus, mLowBatteryReminderLevels[1], mLowBatteryReminderLevels[0], estimate.getEstimateMillis(), + estimate.getAverageDischargeTime(), mEnhancedEstimates.getSevereWarningThreshold(), mEnhancedEstimates.getLowWarningThreshold(), estimate.isBasedOnUsage(), mEnhancedEstimates.getLowWarningEnabled()); @@ -316,7 +318,8 @@ public class PowerUI extends SystemUI { return estimate; } return new Estimate(mLastBatteryStateSnapshot.getTimeRemainingMillis(), - mLastBatteryStateSnapshot.isBasedOnUsage()); + mLastBatteryStateSnapshot.isBasedOnUsage(), + mLastBatteryStateSnapshot.getAverageTimeToDischargeMillis()); } @VisibleForTesting diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java index 2da68249d8c4..6adaa0ddbfd2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java @@ -149,6 +149,13 @@ public class KeyguardAffordanceView extends ImageView { updateIconColor(); } + /** + * If current drawable should be tinted. + */ + public boolean shouldTint() { + return mShouldTint; + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); @@ -168,6 +175,9 @@ public class KeyguardAffordanceView extends ImageView { } public void setPreviewView(View v) { + if (mPreviewView == v) { + return; + } View oldPreviewView = mPreviewView; mPreviewView = v; if (mPreviewView != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java index 059c3f672b69..926d4b6a79b3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java @@ -147,7 +147,14 @@ public class NotificationInterruptionStateProvider { * @return true if the entry should bubble up, false otherwise */ public boolean shouldBubbleUp(NotificationEntry entry) { - StatusBarNotification sbn = entry.notification; + final StatusBarNotification sbn = entry.notification; + if (!entry.canBubble) { + if (DEBUG) { + Log.d(TAG, "No bubble up: not allowed to bubble: " + sbn.getKey()); + } + return false; + } + if (!entry.isBubble()) { if (DEBUG) { Log.d(TAG, "No bubble up: notification " + sbn.getKey() @@ -156,6 +163,15 @@ public class NotificationInterruptionStateProvider { return false; } + final Notification n = sbn.getNotification(); + if (n.getBubbleMetadata() == null || n.getBubbleMetadata().getIntent() == null) { + if (DEBUG) { + Log.d(TAG, "No bubble up: notification: " + sbn.getKey() + + " doesn't have valid metadata"); + } + return false; + } + if (!canHeadsUpCommon(entry)) { return false; } 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 cb64f10d9e8c..5b464a9ecd97 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -337,7 +337,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private void updateRightAffordanceIcon() { IconState state = mRightButton.getIcon(); mRightAffordanceView.setVisibility(!mDozing && state.isVisible ? View.VISIBLE : View.GONE); - mRightAffordanceView.setImageDrawable(state.drawable, state.tint); + if (state.drawable != mRightAffordanceView.getDrawable() + || state.tint != mRightAffordanceView.shouldTint()) { + mRightAffordanceView.setImageDrawable(state.drawable, state.tint); + } mRightAffordanceView.setContentDescription(state.contentDescription); } @@ -389,7 +392,10 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private void updateLeftAffordanceIcon() { IconState state = mLeftButton.getIcon(); mLeftAffordanceView.setVisibility(!mDozing && state.isVisible ? View.VISIBLE : View.GONE); - mLeftAffordanceView.setImageDrawable(state.drawable, state.tint); + if (state.drawable != mLeftAffordanceView.getDrawable() + || state.tint != mLeftAffordanceView.shouldTint()) { + mLeftAffordanceView.setImageDrawable(state.drawable, state.tint); + } mLeftAffordanceView.setContentDescription(state.contentDescription); } @@ -715,11 +721,6 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL updateLeftPreview(); } - public void onKeyguardShowingChanged() { - updateLeftAffordance(); - inflateCameraPreview(); - } - private void setRightButton(IntentButton button) { mRightButton = button; updateRightAffordanceIcon(); 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 57b2ee9d893c..2207e0412949 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -1304,7 +1304,6 @@ public class NotificationPanelView extends PanelView implements mKeyguardStatusBar.setAlpha(1f); mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE); if (keyguardShowing && oldState != mBarState) { - mKeyguardBottomArea.onKeyguardShowingChanged(); if (mQs != null) { mQs.hideImmediately(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java index 273fa55ee9d8..fde1455b0af0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java @@ -31,10 +31,10 @@ import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.settingslib.fuelgauge.BatterySaverUtils; +import com.android.settingslib.fuelgauge.Estimate; import com.android.settingslib.utils.PowerUtil; import com.android.systemui.Dependency; import com.android.systemui.power.EnhancedEstimates; -import com.android.systemui.power.Estimate; import java.io.FileDescriptor; import java.io.PrintWriter; diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java index 40a53571ddf0..8b0ba9448d2b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -16,6 +16,7 @@ package com.android.systemui.bubbles; +import static android.app.Notification.FLAG_BUBBLE; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static com.google.common.truth.Truth.assertThat; @@ -25,6 +26,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -47,15 +49,18 @@ import androidx.test.filters.SmallTest; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationTestHelper; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; +import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider; import com.android.systemui.statusbar.notification.collection.NotificationData; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.StatusBarWindowController; import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.HeadsUpManager; import org.junit.Before; import org.junit.Test; @@ -138,7 +143,7 @@ public class BubbleControllerTest extends SysuiTestCase { // Some bubbles want to suppress notifs Notification.BubbleMetadata suppressNotifMetadata = - getBuilder().setSuppressInitialNotification(true).build(); + getBuilder().setSuppressNotification(true).build(); mSuppressNotifRow = mNotificationTestHelper.createBubble(suppressNotifMetadata, FOREGROUND_TEST_PKG_NAME); @@ -146,9 +151,15 @@ public class BubbleControllerTest extends SysuiTestCase { when(mNotificationEntryManager.getNotificationData()).thenReturn(mNotificationData); when(mNotificationData.getChannel(mRow.getEntry().key)).thenReturn(mRow.getEntry().channel); + TestableNotificationInterruptionStateProvider interruptionStateProvider = + new TestableNotificationInterruptionStateProvider(mContext); + interruptionStateProvider.setUpWithPresenter( + mock(NotificationPresenter.class), + mock(HeadsUpManager.class), + mock(NotificationInterruptionStateProvider.HeadsUpSuppressor.class)); mBubbleData = new BubbleData(mContext); mBubbleController = new TestableBubbleController(mContext, mStatusBarWindowController, - mBubbleData, mConfigurationController); + mBubbleData, mConfigurationController, interruptionStateProvider); mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener); mBubbleController.setExpandListener(mBubbleExpandListener); @@ -487,12 +498,27 @@ public class BubbleControllerTest extends SysuiTestCase { verify(mDeleteIntent, times(2)).send(); } + @Test + public void testRemoveBubble_noLongerBubbleAfterUpdate() + throws PendingIntent.CanceledException { + mBubbleController.updateBubble(mRow.getEntry()); + assertTrue(mBubbleController.hasBubbles()); + + mRow.getEntry().notification.getNotification().flags &= ~FLAG_BUBBLE; + mEntryListener.onPreEntryUpdated(mRow.getEntry()); + + assertFalse(mBubbleController.hasBubbles()); + verify(mDeleteIntent, never()).send(); + } + static class TestableBubbleController extends BubbleController { // Let's assume surfaces can be synchronized immediately. TestableBubbleController(Context context, StatusBarWindowController statusBarWindowController, BubbleData data, - ConfigurationController configurationController) { - super(context, statusBarWindowController, data, Runnable::run, configurationController); + ConfigurationController configurationController, + NotificationInterruptionStateProvider interruptionStateProvider) { + super(context, statusBarWindowController, data, Runnable::run, + configurationController, interruptionStateProvider); } @Override @@ -501,6 +527,15 @@ public class BubbleControllerTest extends SysuiTestCase { } } + public static class TestableNotificationInterruptionStateProvider extends + NotificationInterruptionStateProvider { + + public TestableNotificationInterruptionStateProvider(Context context) { + super(context); + mUseHeadsUp = true; + } + } + /** * @return basic {@link android.app.Notification.BubbleMetadata.Builder} */ diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java index 5928a07487d9..161b40979e11 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java @@ -40,6 +40,7 @@ import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.testing.TestableResources; +import com.android.settingslib.fuelgauge.Estimate; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.power.PowerUI.WarningsUI; @@ -358,7 +359,7 @@ public class PowerUITest extends SysuiTestCase { @Test public void testRefreshEstimateIfNeeded_onlyQueriesEstimateOnBatteryLevelChangeOrNull() { mPowerUI.start(); - Estimate estimate = new Estimate(BELOW_HYBRID_THRESHOLD, true); + Estimate estimate = new Estimate(BELOW_HYBRID_THRESHOLD, true, 0); when(mEnhancedEstimates.isHybridNotificationEnabled()).thenReturn(true); when(mEnhancedEstimates.getLowWarningThreshold()).thenReturn(PowerUI.THREE_HOURS_IN_MILLIS); when(mEnhancedEstimates.getSevereWarningThreshold()).thenReturn(ONE_HOUR_MILLIS); @@ -371,21 +372,21 @@ public class PowerUITest extends SysuiTestCase { assertThat(refreshedEstimate.getEstimateMillis()).isEqualTo(BELOW_HYBRID_THRESHOLD); BatteryStateSnapshot snapshot = new BatteryStateSnapshot( BATTERY_LEVEL_10, false, false, 0, BatteryManager.BATTERY_HEALTH_GOOD, - 0, 0, -1, 0, 0, false, true); + 0, 0, -1, 0, 0, 0, false, true); mPowerUI.mLastBatteryStateSnapshot = snapshot; // query again since the estimate was -1 - estimate = new Estimate(BELOW_SEVERE_HYBRID_THRESHOLD, true); + estimate = new Estimate(BELOW_SEVERE_HYBRID_THRESHOLD, true, 0); when(mEnhancedEstimates.getEstimate()).thenReturn(estimate); refreshedEstimate = mPowerUI.refreshEstimateIfNeeded(); assertThat(refreshedEstimate.getEstimateMillis()).isEqualTo(BELOW_SEVERE_HYBRID_THRESHOLD); snapshot = new BatteryStateSnapshot( BATTERY_LEVEL_10, false, false, 0, BatteryManager.BATTERY_HEALTH_GOOD, 0, - 0, BELOW_SEVERE_HYBRID_THRESHOLD, 0, 0, false, true); + 0, BELOW_SEVERE_HYBRID_THRESHOLD, 0, 0, 0, false, true); mPowerUI.mLastBatteryStateSnapshot = snapshot; // Battery level hasn't changed, so we don't query again - estimate = new Estimate(BELOW_HYBRID_THRESHOLD, true); + estimate = new Estimate(BELOW_HYBRID_THRESHOLD, true, 0); when(mEnhancedEstimates.getEstimate()).thenReturn(estimate); refreshedEstimate = mPowerUI.refreshEstimateIfNeeded(); assertThat(refreshedEstimate.getEstimateMillis()).isEqualTo(BELOW_SEVERE_HYBRID_THRESHOLD); @@ -543,13 +544,14 @@ public class PowerUITest extends SysuiTestCase { public boolean mIsBasedOnUsage = true; public boolean mIsHybrid = true; public boolean mIsLowLevelWarningEnabled = true; + private long mAverageTimeToDischargeMillis = Duration.ofHours(24).toMillis(); public BatteryStateSnapshot get() { if (mIsHybrid) { return new BatteryStateSnapshot(mBatteryLevel, mIsPowerSaver, mPlugged, mBucket, mBatteryStatus, mSevereLevelThreshold, mLowLevelThreshold, - mTimeRemainingMillis, mSevereThresholdMillis, mLowThresholdMillis, - mIsBasedOnUsage, mIsLowLevelWarningEnabled); + mTimeRemainingMillis, mAverageTimeToDischargeMillis, mSevereThresholdMillis, + mLowThresholdMillis, mIsBasedOnUsage, mIsLowLevelWarningEnabled); } else { return new BatteryStateSnapshot(mBatteryLevel, mIsPowerSaver, mPlugged, mBucket, mBatteryStatus, mSevereLevelThreshold, mLowLevelThreshold); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java index 8cc1571b925f..e4b90c54d5b3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java @@ -178,7 +178,10 @@ public class NotificationTestHelper { Notification n = createNotification(false /* isGroupSummary */, null /* groupKey */, bubbleMetadata); n.flags |= FLAG_BUBBLE; - return generateRow(n, pkg, UID, USER_HANDLE, 0 /* extraInflationFlags */, IMPORTANCE_HIGH); + ExpandableNotificationRow row = generateRow(n, pkg, UID, USER_HANDLE, + 0 /* extraInflationFlags */, IMPORTANCE_HIGH); + row.getEntry().canBubble = true; + return row; } /** diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index d0ca861d8d3b..9b4293d484bc 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -256,6 +256,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Whether to allow devices placed in vr headset viewers to have an alternative Home intent. static final boolean ENABLE_VR_HEADSET_HOME_CAPTURE = true; + // must match: config_shortPressOnPowerBehavior in config.xml static final int SHORT_PRESS_POWER_NOTHING = 0; static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1; static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2; @@ -263,29 +264,34 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final int SHORT_PRESS_POWER_GO_HOME = 4; static final int SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME = 5; + // must match: config_LongPressOnPowerBehavior in config.xml static final int LONG_PRESS_POWER_NOTHING = 0; static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1; static final int LONG_PRESS_POWER_SHUT_OFF = 2; static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3; static final int LONG_PRESS_POWER_GO_TO_VOICE_ASSIST = 4; + static final int LONG_PRESS_POWER_ASSISTANT = 5; // Settings.Secure.ASSISTANT + // must match: config_veryLongPresOnPowerBehavior in config.xml static final int VERY_LONG_PRESS_POWER_NOTHING = 0; static final int VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS = 1; + // must match: config_doublePressOnPowerBehavior in config.xml static final int MULTI_PRESS_POWER_NOTHING = 0; static final int MULTI_PRESS_POWER_THEATER_MODE = 1; static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2; + // must match: config_longPressOnBackBehavior in config.xml static final int LONG_PRESS_BACK_NOTHING = 0; static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1; - // These need to match the documentation/constant in - // core/res/res/values/config.xml + // must match: config_longPressOnHomeBehavior in config.xml static final int LONG_PRESS_HOME_NOTHING = 0; static final int LONG_PRESS_HOME_ALL_APPS = 1; static final int LONG_PRESS_HOME_ASSIST = 2; static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_ASSIST; + // must match: config_doubleTapOnHomeBehavior in config.xml static final int DOUBLE_TAP_HOME_NOTHING = 0; static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1; @@ -770,6 +776,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.Global.getUriFor( + Settings.Global.POWER_BUTTON_LONG_PRESS), false, this, + UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.Global.getUriFor( + Settings.Global.POWER_BUTTON_VERY_LONG_PRESS), false, this, + UserHandle.USER_ALL); updateSettings(); } @@ -1195,38 +1207,38 @@ public class PhoneWindowManager implements WindowManagerPolicy { private void powerLongPress() { final int behavior = getResolvedLongPressOnPowerBehavior(); switch (behavior) { - case LONG_PRESS_POWER_NOTHING: - break; - case LONG_PRESS_POWER_GLOBAL_ACTIONS: - mPowerKeyHandled = true; - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, - "Power - Long Press - Global Actions"); - showGlobalActionsInternal(); - break; - case LONG_PRESS_POWER_SHUT_OFF: - case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM: - mPowerKeyHandled = true; - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, - "Power - Long Press - Shut Off"); - sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); - mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF); - break; - case LONG_PRESS_POWER_GO_TO_VOICE_ASSIST: - mPowerKeyHandled = true; - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, - "Power - Long Press - Go To Voice Assist"); - final boolean keyguardActive = mKeyguardDelegate == null - ? false - : mKeyguardDelegate.isShowing(); - if (!keyguardActive) { - Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST); - if (mAllowStartActivityForLongPressOnPowerDuringSetup) { - mContext.startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); - } else { - startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); - } - } - break; + case LONG_PRESS_POWER_NOTHING: + break; + case LONG_PRESS_POWER_GLOBAL_ACTIONS: + mPowerKeyHandled = true; + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, + "Power - Long Press - Global Actions"); + showGlobalActionsInternal(); + break; + case LONG_PRESS_POWER_SHUT_OFF: + case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM: + mPowerKeyHandled = true; + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, + "Power - Long Press - Shut Off"); + sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); + mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF); + break; + case LONG_PRESS_POWER_GO_TO_VOICE_ASSIST: + mPowerKeyHandled = true; + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, + "Power - Long Press - Go To Voice Assist"); + // Some devices allow the voice assistant intent during setup (and use that intent + // to launch something else, like Settings). So we explicitly allow that via the + // config_allowStartActivityForLongPressOnPowerInSetup resource in config.xml. + launchVoiceAssist(mAllowStartActivityForLongPressOnPowerDuringSetup); + break; + case LONG_PRESS_POWER_ASSISTANT: + mPowerKeyHandled = true; + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, + "Power - Long Press - Go To Assistant"); + final int powerKeyDeviceId = Integer.MIN_VALUE; + launchAssistAction(null, powerKeyDeviceId); + break; } } @@ -1250,13 +1262,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { case LONG_PRESS_BACK_NOTHING: break; case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST: - final boolean keyguardActive = mKeyguardDelegate == null - ? false - : mKeyguardDelegate.isShowing(); - if (!keyguardActive) { - Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST); - startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); - } + launchVoiceAssist(false /* allowDuringSetup */); break; } } @@ -1999,6 +2005,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { mHasSoftInput = hasSoftInput; updateRotation = true; } + + mLongPressOnPowerBehavior = Settings.Global.getInt(resolver, + Settings.Global.POWER_BUTTON_LONG_PRESS, + mContext.getResources().getInteger( + com.android.internal.R.integer.config_longPressOnPowerBehavior)); + mVeryLongPressOnPowerBehavior = Settings.Global.getInt(resolver, + Settings.Global.POWER_BUTTON_VERY_LONG_PRESS, + mContext.getResources().getInteger( + com.android.internal.R.integer.config_veryLongPressOnPowerBehavior)); } if (updateRotation) { updateRotation(true); @@ -3225,6 +3240,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { return 0; } + // There are several different flavors of "assistant" that can be launched from + // various parts of the UI. + + /** starts ACTION_SEARCH_LONG_PRESS, usually a voice search prompt */ private void launchAssistLongPressAction() { performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, "Assist - Long Press"); @@ -3246,6 +3265,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + /** Asks the status bar to startAssist(), usually a full "assistant" interface */ private void launchAssistAction(String hint, int deviceId) { sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); if (!isUserSetupComplete()) { @@ -3276,12 +3296,30 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + /** Launches ACTION_VOICE_ASSIST. Does nothing on keyguard. */ + private void launchVoiceAssist(boolean allowDuringSetup) { + final boolean keyguardActive = mKeyguardDelegate == null + ? false + : mKeyguardDelegate.isShowing(); + if (!keyguardActive) { + Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST); + startActivityAsUser(intent, null, UserHandle.CURRENT_OR_SELF, + allowDuringSetup); + } + + } + private void startActivityAsUser(Intent intent, UserHandle handle) { startActivityAsUser(intent, null, handle); } private void startActivityAsUser(Intent intent, Bundle bundle, UserHandle handle) { - if (isUserSetupComplete()) { + startActivityAsUser(intent, bundle, handle, false /* allowDuringSetup */); + } + + private void startActivityAsUser(Intent intent, Bundle bundle, UserHandle handle, + boolean allowDuringSetup) { + if (allowDuringSetup || isUserSetupComplete()) { mContext.startActivityAsUser(intent, bundle, handle); } else { Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent); @@ -5541,6 +5579,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { return "LONG_PRESS_POWER_SHUT_OFF"; case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM: return "LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM"; + case LONG_PRESS_POWER_GO_TO_VOICE_ASSIST: + return "LONG_PRESS_POWER_GO_TO_VOICE_ASSIST"; + case LONG_PRESS_POWER_ASSISTANT: + return "LONG_PRESS_POWER_ASSISTANT"; default: return Integer.toString(behavior); } |