summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt4
-rw-r--r--cmds/statsd/src/atoms.proto34
-rw-r--r--cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp99
-rw-r--r--cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h33
-rw-r--r--core/java/android/app/Notification.java8
-rw-r--r--core/java/android/bluetooth/le/ScanFilter.java9
-rw-r--r--core/java/android/content/LocusId.java5
-rw-r--r--core/java/android/content/pm/PackageParser.java14
-rw-r--r--core/java/android/content/pm/ShortcutInfo.java8
-rw-r--r--core/java/android/provider/DeviceConfig.java7
-rw-r--r--core/java/android/provider/Settings.java64
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureContext.java1
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java152
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java13
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java41
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java51
-rw-r--r--core/jni/android_ddm_DdmHandleNativeHeap.cpp25
-rw-r--r--core/jni/android_os_Debug.cpp12
-rw-r--r--core/res/res/layout/chooser_grid.xml17
-rw-r--r--core/res/res/layout/chooser_profile_row.xml32
-rw-r--r--core/res/res/values/config.xml1
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java9
-rw-r--r--core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatterySaverUtils.java3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/fuelgauge/Estimate.kt81
-rw-r--r--packages/SystemUI/src/com/android/keyguard/CarrierTextController.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/Estimate.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerUI.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInterruptionStateProvider.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java138
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java43
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationTestHelper.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java19
-rw-r--r--services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java27
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java73
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java5
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java126
-rw-r--r--services/core/java/com/android/server/stats/StatsCompanionService.java5
50 files changed, 856 insertions, 485 deletions
diff --git a/api/current.txt b/api/current.txt
index 6253dfd4058c..1623bb8ab108 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -8988,8 +8988,8 @@ package android.bluetooth.le {
method public android.bluetooth.le.ScanFilter.Builder setManufacturerData(int, byte[], byte[]);
method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[]);
method public android.bluetooth.le.ScanFilter.Builder setServiceData(android.os.ParcelUuid, byte[], byte[]);
- method public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(android.os.ParcelUuid);
- method public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(android.os.ParcelUuid, android.os.ParcelUuid);
+ method @NonNull public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(@Nullable android.os.ParcelUuid);
+ method @NonNull public android.bluetooth.le.ScanFilter.Builder setServiceSolicitationUuid(@Nullable android.os.ParcelUuid, @Nullable android.os.ParcelUuid);
method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid);
method public android.bluetooth.le.ScanFilter.Builder setServiceUuid(android.os.ParcelUuid, android.os.ParcelUuid);
}
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 12474ce83d11..68a88162a1bb 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -156,7 +156,7 @@ message Atom {
KeyValuePairsAtom key_value_pairs_atom = 83 [(allow_from_any_uid) = true];
VibratorStateChanged vibrator_state_changed = 84;
DeferredJobStatsReported deferred_job_stats_reported = 85;
- ThermalThrottlingStateChanged thermal_throttling = 86;
+ ThermalThrottlingStateChanged thermal_throttling = 86 [deprecated=true];
BiometricAcquired biometric_acquired = 87;
BiometricAuthenticated biometric_authenticated = 88;
BiometricErrorOccurred biometric_error_occurred = 89;
@@ -270,7 +270,7 @@ message Atom {
HiddenApiUsed hidden_api_used = 178 [(allow_from_any_uid) = true];
StyleUIChanged style_ui_changed = 179;
PrivacyIndicatorsInteracted privacy_indicators_interacted =
- 180 [(log_from_module) = "permissioncontroller"];
+ 180 [(log_from_module) = "permissioncontroller"];
AppInstallOnExternalStorageReported app_install_on_external_storage_reported = 181;
NetworkStackReported network_stack_reported = 182 [(log_from_module) = "network_stack"];
AppMovedStorageReported app_moved_storage_reported = 183;
@@ -280,6 +280,7 @@ message Atom {
BluetoothClassOfDeviceReported bluetooth_class_of_device_reported = 187;
IntelligenceEventReported intelligence_event_reported =
188 [(log_from_module) = "intelligence"];
+ ThermalThrottlingSeverityStateChanged thermal_throttling_severity_state_changed = 189;
}
// Pulled events will start at field 10000.
@@ -409,6 +410,7 @@ message KeyValuePairsAtom {
*/
/**
+ * This atom is deprecated starting in Q. Please use ThermalThrottlingSeverityStateChanged.
* Logs when the Thermal service HAL notifies the throttling start/stop events.
*
* Logged from:
@@ -426,14 +428,7 @@ message ThermalThrottlingStateChanged {
}
optional State state = 2;
- // Temperature in deci degrees celsius
optional float temperature = 3;
-
- // Severity of throttling
- optional android.os.ThrottlingSeverityEnum severity = 4;
-
- // Thermistor name
- optional string sensor_name = 5;
}
/**
@@ -2364,6 +2359,27 @@ message BatteryCausedShutdown {
}
/**
+ * Logs when ThermalService receives throttling events.
+ *
+ * Logged from:
+ * frameworks/base/services/core/java/com/android/server/stats/StatsCompanionService.java
+ */
+message ThermalThrottlingSeverityStateChanged {
+ // The type of temperature being reported (CPU, GPU, SKIN, etc)
+ optional android.os.TemperatureTypeEnum sensor_type = 1;
+
+ // The name of the temperature source. Eg. CPU0
+ optional string sensor_name = 2;
+
+ // Temperature in tenths of a degree C.
+ // For BCL, it is decimillivolt, decimilliamps, and percentage * 10.
+ optional int32 temperature_deci_celsius = 3;
+
+ // Relative severity of the throttling, see enum definition.
+ optional android.os.ThrottlingSeverityEnum severity = 4;
+}
+
+/**
* Logs the duration of a davey (jank of >=700ms) when it occurs
*
* Logged from:
diff --git a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp
deleted file mode 100644
index 01c75873fdf9..000000000000
--- a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2017, 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.
- */
-
-#define DEBUG false // STOPSHIP if true
-#include "Log.h"
-
-#include <sstream>
-#include "MemoryLeakTrackUtil.h"
-
-/*
- * The code here originally resided in MediaPlayerService.cpp
- */
-
-// Figure out the abi based on defined macros.
-#if defined(__arm__)
-#define ABI_STRING "arm"
-#elif defined(__aarch64__)
-#define ABI_STRING "arm64"
-#elif defined(__mips__) && !defined(__LP64__)
-#define ABI_STRING "mips"
-#elif defined(__mips__) && defined(__LP64__)
-#define ABI_STRING "mips64"
-#elif defined(__i386__)
-#define ABI_STRING "x86"
-#elif defined(__x86_64__)
-#define ABI_STRING "x86_64"
-#else
-#error "Unsupported ABI"
-#endif
-
-extern std::string backtrace_string(const uintptr_t* frames, size_t frame_count);
-
-namespace android {
-namespace os {
-namespace statsd {
-
-extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize, size_t* infoSize,
- size_t* totalMemory, size_t* backtraceSize);
-
-extern "C" void free_malloc_leak_info(uint8_t* info);
-
-std::string dumpMemInfo(size_t limit) {
- uint8_t* info;
- size_t overallSize;
- size_t infoSize;
- size_t totalMemory;
- size_t backtraceSize;
- get_malloc_leak_info(&info, &overallSize, &infoSize, &totalMemory, &backtraceSize);
-
- size_t count;
- if (info == nullptr || overallSize == 0 || infoSize == 0 ||
- (count = overallSize / infoSize) == 0) {
- VLOG("no malloc info, libc.debug.malloc.program property should be set");
- return std::string();
- }
-
- std::ostringstream oss;
- oss << totalMemory << " bytes in " << count << " allocations\n";
- oss << " ABI: '" ABI_STRING "'"
- << "\n\n";
- if (count > limit) count = limit;
-
- // The memory is sorted based on total size which is useful for finding
- // worst memory offenders. For diffs, sometimes it is preferable to sort
- // based on the backtrace.
- for (size_t i = 0; i < count; i++) {
- struct AllocEntry {
- size_t size; // bit 31 is set if this is zygote allocated memory
- size_t allocations;
- uintptr_t backtrace[];
- };
-
- const AllocEntry* const e = (AllocEntry*)(info + i * infoSize);
-
- oss << (e->size * e->allocations) << " bytes ( " << e->size << " bytes * " << e->allocations
- << " allocations )\n";
- oss << backtrace_string(e->backtrace, backtraceSize) << "\n";
- }
- oss << "\n";
- free_malloc_leak_info(info);
- return oss.str();
-}
-
-} // namespace statsd
-} // namespace os
-} // namespace android \ No newline at end of file
diff --git a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h b/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h
deleted file mode 100644
index 444ed92cc9bb..000000000000
--- a/cmds/statsd/src/guardrail/MemoryLeakTrackUtil.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2017, 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.
- */
-#pragma once
-
-#include <iostream>
-
-namespace android {
-namespace os {
-namespace statsd {
-/*
- * Dump the heap memory of the calling process, sorted by total size
- * (allocation size * number of allocations).
- *
- * limit is the number of unique allocations to return.
- */
-extern std::string dumpMemInfo(size_t limit);
-
-} // namespace statsd
-} // namespace os
-} // namespace android \ No newline at end of file
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0c6c77f8e36b..d0361b7e1118 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3165,8 +3165,8 @@ public class Notification implements Parcelable
/**
* Gets the {@link LocusId} associated with this notification.
*
- * <p>Used by the device's intelligence services to correlate objects (such as
- * {@link ShortcutInfo} and {@link ContentCaptureContext}) that are correlated.
+ * <p>Used by the Android system to correlate objects (such as
+ * {@link ShortcutInfo} and {@link ContentCaptureContext}).
*/
@Nullable
public LocusId getLocusId() {
@@ -3534,8 +3534,8 @@ public class Notification implements Parcelable
* Sets the {@link LocusId} associated with this notification.
*
* <p>This method should be called when the {@link LocusId} is used in other places (such
- * as {@link ShortcutInfo} and {@link ContentCaptureContext}) so the device's intelligence
- * services can correlate them.
+ * as {@link ShortcutInfo} and {@link ContentCaptureContext}) so the Android system can
+ * correlate them.
*/
@NonNull
public Builder setLocusId(@Nullable LocusId locusId) {
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index 78140cf65d07..07ba2c6680a9 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -16,6 +16,7 @@
package android.bluetooth.le;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -586,7 +587,8 @@ public final class ScanFilter implements Parcelable {
/**
* Set filter on service solicitation uuid.
*/
- public Builder setServiceSolicitationUuid(ParcelUuid serviceSolicitationUuid) {
+ public @NonNull Builder setServiceSolicitationUuid(
+ @Nullable ParcelUuid serviceSolicitationUuid) {
mServiceSolicitationUuid = serviceSolicitationUuid;
return this;
}
@@ -601,8 +603,9 @@ public final class ScanFilter implements Parcelable {
* @throws IllegalArgumentException If {@code serviceSolicitationUuid} is {@code null} but
* {@code serviceSolicitationUuidMask} is not {@code null}.
*/
- public Builder setServiceSolicitationUuid(ParcelUuid serviceSolicitationUuid,
- ParcelUuid solicitationUuidMask) {
+ public @NonNull Builder setServiceSolicitationUuid(
+ @Nullable ParcelUuid serviceSolicitationUuid,
+ @Nullable ParcelUuid solicitationUuidMask) {
if (mServiceSolicitationUuidMask != null && mServiceSolicitationUuid == null) {
throw new IllegalArgumentException(
"SolicitationUuid is null while SolicitationUuidMask is not null!");
diff --git a/core/java/android/content/LocusId.java b/core/java/android/content/LocusId.java
index 283cea00b192..613765fd826a 100644
--- a/core/java/android/content/LocusId.java
+++ b/core/java/android/content/LocusId.java
@@ -29,9 +29,8 @@ import java.io.PrintWriter;
* backup / restore.
*
* <p>Locus is a new concept introduced on
- * {@link android.os.Build.VERSION_CODES#Q Android Q} and it lets the intelligence service provided
- * by the Android System to correlate state between different subsystems such as content capture,
- * shortcuts, and notifications.
+ * {@link android.os.Build.VERSION_CODES#Q Android Q} and it lets the Android system correlate
+ * state between different subsystems such as content capture, shortcuts, and notifications.
*
* <p>For example, if your app provides an activiy representing a chat between 2 users
* (say {@code A} and {@code B}, this chat state could be represented by:
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/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 1f82fa6b57e3..41be38a6e8dd 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -991,8 +991,8 @@ public final class ShortcutInfo implements Parcelable {
* Sets the {@link LocusId} associated with this shortcut.
*
* <p>This method should be called when the {@link LocusId} is used in other places (such
- * as {@link Notification} and {@link ContentCaptureContext}) so the device's intelligence
- * services can correlate them.
+ * as {@link Notification} and {@link ContentCaptureContext}) so the Android system can
+ * correlate them.
*/
@NonNull
public Builder setLocusId(@NonNull LocusId locusId) {
@@ -1325,8 +1325,8 @@ public final class ShortcutInfo implements Parcelable {
/**
* Gets the {@link LocusId} associated with this shortcut.
*
- * <p>Used by the device's intelligence services to correlate objects (such as
- * {@link Notification} and {@link ContentCaptureContext}) that are correlated.
+ * <p>Used by the Android system to correlate objects (such as
+ * {@link Notification} and {@link ContentCaptureContext}).
*/
@Nullable
public LocusId getLocusId() {
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 6c498c736854..9215de14c21f 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -267,6 +267,13 @@ public final class DeviceConfig {
public static final String NAMESPACE_CONTACTS_PROVIDER = "contacts_provider";
/**
+ * Namespace for settings ui related features
+ *
+ * @hide
+ */
+ public static final String NAMESPACE_SETTINGS_UI = "settings_ui";
+
+ /**
* List of namespaces which can be read without READ_DEVICE_CONFIG permission
*
* @hide
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/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index 94e548fa0eeb..1692051924f4 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -261,6 +261,7 @@ public final class ContentCaptureContext implements Parcelable {
* example).
* <li>A unique identifier of the application state (for example, a conversation between
* 2 users in a chat app).
+ * </ul>
*
* <p>See {@link ContentCaptureManager} for more info about the content capture context.
*
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 26454c055932..a9770731dbc7 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -29,7 +29,6 @@ import android.annotation.UiThread;
import android.content.ComponentName;
import android.content.ContentCaptureOptions;
import android.content.Context;
-import android.graphics.Canvas;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -51,61 +50,61 @@ import java.util.ArrayList;
import java.util.Set;
/**
- * <p>The {@link ContentCaptureManager} provides additional ways for for apps to
- * integrate with the content capture subsystem.
+ * Content capture is mechanism used to let apps notify the Android system of events associated with
+ * views.
*
- * <p>Content capture provides real-time, continuous capture of application activity, display and
- * events to an intelligence service that is provided by the Android system. The intelligence
- * service then uses that info to mediate and speed user journey through different apps. For
- * example, when the user receives a restaurant address in a chat app and switchs to a map app
- * to search for that restaurant, the intelligence service could offer an autofill dialog to
- * let the user automatically select its address.
- *
- * <p>Content capture was designed with two major concerns in mind: privacy and performance.
- *
- * <ul>
- * <li><b>Privacy:</b> the intelligence service is a trusted component provided that is provided
- * by the device manufacturer and that cannot be changed by the user (although the user can
- * globaly disable content capture using the Android Settings app). This service can only use the
- * data for in-device machine learning, which is enforced both by process isolation and
- * <a href="https://source.android.com/compatibility/cdd">CDD requirements</a>.
- * <li><b>Performance:</b> content capture is highly optimized to minimize its impact in the app
- * jankiness and overall device system health. For example, its only enabled on apps (or even
- * specific activities from an app) that were explicitly whitelisted by the intelligence service,
- * and it buffers the events so they are sent in a batch to the service (see
- * {@link #isContentCaptureEnabled()} for other cases when its disabled).
- * </ul>
- *
- * <p>In fact, before using this manager, the app developer should check if it's available. Example:
- * <code>
+ * <p>Before using this manager, you should check if it's available. Example:
+ * <pre><code>
* ContentCaptureManager mgr = context.getSystemService(ContentCaptureManager.class);
* if (mgr != null && mgr.isContentCaptureEnabled()) {
* // ...
* }
- * </code>
+ * </code></pre>
*
- * <p>App developers usually don't need to explicitly interact with content capture, except when the
- * app:
+ * <p>To support content capture, you must notifiy the Android system of the following events:
*
* <ul>
- * <li>Can define a contextual {@link android.content.LocusId} to identify unique state (such as a
- * conversation between 2 chat users).
- * <li>Can have multiple view hierarchies with different contextual meaning (for example, a
- * browser app with multiple tabs, each representing a different URL).
- * <li>Contains custom views (that extend View directly and are not provided by the standard
- * Android SDK.
- * <li>Contains views that provide their own virtual hierarchy (like a web browser that render the
- * HTML elements using a Canvas).
+ * <li>When a visible view is laid out, call
+ * {@link ContentCaptureSession#notifyViewAppeared(ViewStructure)}.
+ * <li>When a view becomes invisible or is removed from the view hierarchy, call
+ * {@link ContentCaptureSession#notifyViewDisappeared(android.view.autofill.AutofillId)}.
+ * <li>When the view represents text and the text value changed, call {@link
+ * ContentCaptureSession#notifyViewTextChanged(android.view.autofill.AutofillId, CharSequence)}.
* </ul>
*
+ * <p>You can get a blank content capture structure using
+ * {@link ContentCaptureSession#newViewStructure(View)}, then populate its relevant fields.
+ * Here's an example of the relevant methods for an {@code EditText}-like view:
+ *
+ * <pre><code>
+ * public class MyEditText extends View {
+ *
+ * private void populateContentCaptureStructure(@NonNull ViewStructure structure) {
+ * structure.setText(getText(), getSelectionStart(), getSelectionEnd());
+ * structure.setHint(getHint());
+ * structure.setInputType(getInputType());
+ * // set other properties like setTextIdEntry(), setTextLines(), setTextStyle(),
+ * // setMinTextEms(), setMaxTextEms(), setMaxTextLength()
+ * }
+ *
+ * private void onTextChanged() {
+ * if (isLaidOut() && isTextEditable()) {
+ * ContentCaptureManager mgr = mContext.getSystemService(ContentCaptureManager.class);
+ * if (cm != null && cm.isContentCaptureEnabled()) {
+ * ContentCaptureSession session = getContentCaptureSession();
+ * if (session != null) {
+ * session.notifyViewTextChanged(getAutofillId(), getText());
+ * }
+ * }
+ * }
+ * </code></pre>
+ *
* <p>The main integration point with content capture is the {@link ContentCaptureSession}. A "main"
- * session is automatically created by the Android System when content capture is enabled for the
- * activity and its used by the standard Android views to notify the content capture service of
- * events such as views being added, views been removed, and text changed by user input. The session
- * could have a {@link ContentCaptureContext} to provide more contextual info about it, such as
- * the locus associated with the view hierarchy (see {@link android.content.LocusId} for more info
- * about locus). By default, the main session doesn't have a {@code ContentCaptureContext}, but you
- * can change it after its created. Example:
+ * session is automatically created by the Android system when content capture is enabled for the
+ * activity. The session could have a {@link ContentCaptureContext} to provide more contextual info
+ * about it, such as the locus associated with the view hierarchy
+ * (see {@link android.content.LocusId} for more info about locus). By default, the main session
+ * doesn't have a {@code ContentCaptureContext}, but you can change it after its created. Example:
*
* <pre><code>
* protected void onCreate(Bundle savedInstanceState) {
@@ -145,54 +144,6 @@ import java.util.Set;
* }
* </code></pre>
*
- * <p>If your activity has custom views (i.e., views that extend {@link View} directly and provide
- * just one logical view, not a virtual tree hiearchy) and it provides content that's relevant for
- * content capture (as of {@link android.os.Build.VERSION_CODES#Q Android Q}, the only relevant
- * content is text), then your view implementation should:
- *
- * <ul>
- * <li>Set it as important for content capture.
- * <li>Fill {@link ViewStructure} used for content capture.
- * <li>Notify the {@link ContentCaptureSession} when the text is changed by user input.
- * </ul>
- *
- * <p>Here's an example of the relevant methods for an {@code EditText}-like view:
- *
- * <pre><code>
- * public class MyEditText extends View {
- *
- * public MyEditText(...) {
- * if (getImportantForContentCapture() == IMPORTANT_FOR_CONTENT_CAPTURE_AUTO) {
- * setImportantForContentCapture(IMPORTANT_FOR_CONTENT_CAPTURE_YES);
- * }
- * }
- *
- * public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) {
- * super.onProvideContentCaptureStructure(structure, flags);
- *
- * structure.setText(getText(), getSelectionStart(), getSelectionEnd());
- * structure.setHint(getHint());
- * structure.setInputType(getInputType());
- * // set other properties like setTextIdEntry(), setTextLines(), setTextStyle(),
- * // setMinTextEms(), setMaxTextEms(), setMaxTextLength()
- * }
- *
- * private void onTextChanged() {
- * if (isLaidOut() && isImportantForContentCapture() && isTextEditable()) {
- * ContentCaptureManager mgr = mContext.getSystemService(ContentCaptureManager.class);
- * if (cm != null && cm.isContentCaptureEnabled()) {
- * ContentCaptureSession session = getContentCaptureSession();
- * if (session != null) {
- * session.notifyViewTextChanged(getAutofillId(), getText());
- * }
- * }
- * }
- * </code></pre>
- *
- * <p>If your view provides its own virtual hierarchy (for example, if it's a browser that draws
- * the HTML using {@link Canvas} or native libraries in a different render process), then the view
- * is also responsible to notify the session when the virtual elements appear and disappear -
- * see {@link ContentCaptureSession#newViewStructure(View)} for more info.
*/
@SystemService(Context.CONTENT_CAPTURE_MANAGER_SERVICE)
public final class ContentCaptureManager {
@@ -473,17 +424,6 @@ public final class ContentCaptureManager {
/**
* Checks whether content capture is enabled for this activity.
- *
- * <p>There are many reasons it could be disabled, such as:
- * <ul>
- * <li>App itself disabled content capture through {@link #setContentCaptureEnabled(boolean)}.
- * <li>Intelligence service did not whitelist content capture for this activity's package.
- * <li>Intelligence service did not whitelist content capture for this specific activity.
- * <li>Intelligence service disabled content capture globally.
- * <li>User disabled content capture globally through the Android Settings app.
- * <li>Device manufacturer (OEM) disabled content capture globally.
- * <li>Transient errors, such as intelligence service package being updated.
- * </ul>
*/
public boolean isContentCaptureEnabled() {
if (mOptions.lite) return false;
@@ -503,9 +443,9 @@ public final class ContentCaptureManager {
* Gets the list of conditions for when content capture should be allowed.
*
* <p>This method is typically used by web browsers so they don't generate unnecessary content
- * capture events for websites the content capture service is not interested on.
+ * capture events for some websites.
*
- * @return list of conditions, or {@code null} if the service didn't set any restriction
+ * @return list of conditions, or {@code null} if there isn't any restriction
* (in which case content capture events should always be generated). If the list is empty,
* then it should not generate any event at all.
*/
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 17a1fb405321..210dea1894bf 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -41,8 +41,7 @@ import java.util.ArrayList;
import java.util.Random;
/**
- * Session used to notify a system-provided Content Capture service about events associated with
- * views.
+ * Session used to notify the Android system about events associated with views.
*/
public abstract class ContentCaptureSession implements AutoCloseable {
@@ -306,7 +305,7 @@ public abstract class ContentCaptureSession implements AutoCloseable {
}
/**
- * Destroys this session, flushing out all pending notifications to the service.
+ * Destroys this session, flushing out all pending notifications.
*
* <p>Once destroyed, any new notification will be dropped.
*/
@@ -354,7 +353,7 @@ public abstract class ContentCaptureSession implements AutoCloseable {
}
/**
- * Notifies the Content Capture Service that a node has been added to the view structure.
+ * Notifies the Android system that a node has been added to the view structure.
*
* @param node node that has been added.
*/
@@ -372,7 +371,7 @@ public abstract class ContentCaptureSession implements AutoCloseable {
abstract void internalNotifyViewAppeared(@NonNull ViewNode.ViewStructureImpl node);
/**
- * Notifies the Content Capture Service that a node has been removed from the view structure.
+ * Notifies the Android system that a node has been removed from the view structure.
*
* @param id id of the node that has been removed.
*/
@@ -386,7 +385,7 @@ public abstract class ContentCaptureSession implements AutoCloseable {
abstract void internalNotifyViewDisappeared(@NonNull AutofillId id);
/**
- * Notifies the Content Capture Service that many nodes has been removed from a virtual view
+ * Notifies the Android system that many nodes has been removed from a virtual view
* structure.
*
* <p>Should only be called by views that handle their own virtual view hierarchy.
@@ -412,7 +411,7 @@ public abstract class ContentCaptureSession implements AutoCloseable {
}
/**
- * Notifies the Intelligence Service that the value of a text node has been changed.
+ * Notifies the Android system that the value of a text node has been changed.
*
* @param id of the node.
* @param text new text.
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 744503afc958..83801157d0a9 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -200,7 +200,6 @@ public class ChooserActivity extends ResolverActivity {
private ChooserListAdapter mChooserListAdapter;
private ChooserRowAdapter mChooserRowAdapter;
- private Drawable mChooserRowLayer;
private int mChooserRowServiceSpacing;
/** {@link ChooserActivity#getBaseScore} */
@@ -468,7 +467,6 @@ public class ChooserActivity extends ResolverActivity {
.registerPredictionUpdates(this.getMainExecutor(), mAppPredictorCallback);
}
- mChooserRowLayer = getResources().getDrawable(R.drawable.chooser_row_layer_list, null);
mChooserRowServiceSpacing = getResources()
.getDimensionPixelSize(R.dimen.chooser_service_spacing);
@@ -1952,6 +1950,7 @@ public class ChooserActivity extends ResolverActivity {
int offset = 0;
int rowsToShow = mChooserRowAdapter.getContentPreviewRowCount()
+ + mChooserRowAdapter.getProfileRowCount()
+ mChooserRowAdapter.getServiceTargetRowCount()
+ mChooserRowAdapter.getCallerAndRankedTargetRowCount();
@@ -1971,7 +1970,7 @@ public class ChooserActivity extends ResolverActivity {
}
int lastHeight = 0;
- rowsToShow = Math.max(3, rowsToShow);
+ rowsToShow = Math.min(4, rowsToShow);
for (int i = 0; i < Math.min(rowsToShow, mAdapterView.getChildCount()); i++) {
lastHeight = mAdapterView.getChildAt(i).getHeight();
offset += lastHeight;
@@ -2447,6 +2446,7 @@ public class ChooserActivity extends ResolverActivity {
private static final int VIEW_TYPE_DIRECT_SHARE = 0;
private static final int VIEW_TYPE_NORMAL = 1;
private static final int VIEW_TYPE_CONTENT_PREVIEW = 2;
+ private static final int VIEW_TYPE_PROFILE = 3;
private static final int MAX_TARGETS_PER_ROW_PORTRAIT = 4;
private static final int MAX_TARGETS_PER_ROW_LANDSCAPE = 8;
@@ -2502,9 +2502,9 @@ public class ChooserActivity extends ResolverActivity {
@Override
public int getCount() {
-
return (int) (
getContentPreviewRowCount()
+ + getProfileRowCount()
+ getServiceTargetRowCount()
+ getCallerAndRankedTargetRowCount()
+ Math.ceil(
@@ -2525,6 +2525,10 @@ public class ChooserActivity extends ResolverActivity {
return 1;
}
+ public int getProfileRowCount() {
+ return mChooserListAdapter.getOtherProfile() == null ? 0 : 1;
+ }
+
public int getCallerAndRankedTargetRowCount() {
return (int) Math.ceil(
((float) mChooserListAdapter.getCallerTargetCount()
@@ -2560,6 +2564,10 @@ public class ChooserActivity extends ResolverActivity {
return createContentPreviewView(convertView, parent);
}
+ if (viewType == VIEW_TYPE_PROFILE) {
+ return createProfileView(convertView, parent);
+ }
+
if (convertView == null) {
holder = createViewHolder(viewType, parent);
} else {
@@ -2577,6 +2585,10 @@ public class ChooserActivity extends ResolverActivity {
return VIEW_TYPE_CONTENT_PREVIEW;
}
+ if (getProfileRowCount() == 1 && position == getContentPreviewRowCount()) {
+ return VIEW_TYPE_PROFILE;
+ }
+
final int start = getFirstRowPosition(position);
final int startType = mChooserListAdapter.getPositionTargetType(start);
@@ -2589,7 +2601,7 @@ public class ChooserActivity extends ResolverActivity {
@Override
public int getViewTypeCount() {
- return 3;
+ return 4;
}
private ViewGroup createContentPreviewView(View convertView, ViewGroup parent) {
@@ -2605,6 +2617,17 @@ public class ChooserActivity extends ResolverActivity {
(ViewGroup) convertView, parent);
}
+ private View createProfileView(View convertView, ViewGroup parent) {
+ View profileRow = convertView != null ? convertView : mLayoutInflater.inflate(
+ R.layout.chooser_profile_row, parent, false);
+ profileRow.setBackground(
+ getResources().getDrawable(R.drawable.chooser_row_layer_list, null));
+ mProfileView = profileRow.findViewById(R.id.profile_button);
+ mProfileView.setOnClickListener(ChooserActivity.this::onProfileClick);
+ bindProfileView();
+ return profileRow;
+ }
+
private RowViewHolder loadViewsIntoRow(RowViewHolder holder) {
final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
final int exactSpec = MeasureSpec.makeMeasureSpec(mChooserTargetWidth,
@@ -2723,8 +2746,10 @@ public class ChooserActivity extends ResolverActivity {
final ViewGroup row = holder.getViewGroup();
- if (startType != lastStartType || rowPosition == getContentPreviewRowCount()) {
- row.setBackground(mChooserRowLayer);
+ if (startType != lastStartType
+ || rowPosition == getContentPreviewRowCount() + getProfileRowCount()) {
+ row.setBackground(
+ getResources().getDrawable(R.drawable.chooser_row_layer_list, null));
} else {
row.setBackground(null);
}
@@ -2774,7 +2799,7 @@ public class ChooserActivity extends ResolverActivity {
}
int getFirstRowPosition(int row) {
- row -= getContentPreviewRowCount();
+ row -= getContentPreviewRowCount() + getProfileRowCount();
final int serviceCount = mChooserListAdapter.getServiceTargetCount();
final int serviceRows = (int) Math.ceil((float) serviceCount
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index ad1e767f011a..2849f57d6fc5 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -108,7 +108,7 @@ public class ResolverActivity extends Activity {
private Button mAlwaysButton;
private Button mOnceButton;
private Button mSettingsButton;
- private View mProfileView;
+ protected View mProfileView;
private int mIconDpi;
private int mLastSelected = AbsListView.INVALID_POSITION;
private boolean mResolvingHome = false;
@@ -142,9 +142,7 @@ public class ResolverActivity extends Activity {
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@Override public void onSomePackagesChanged() {
mAdapter.handlePackagesChanged();
- if (mProfileView != null) {
- bindProfileView();
- }
+ bindProfileView();
}
@Override
@@ -336,21 +334,7 @@ public class ResolverActivity extends Activity {
mProfileView = findViewById(R.id.profile_button);
if (mProfileView != null) {
- mProfileView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- final DisplayResolveInfo dri = mAdapter.getOtherProfile();
- if (dri == null) {
- return;
- }
-
- // Do not show the profile switch message anymore.
- mProfileSwitchMessageId = -1;
-
- onTargetSelected(dri, false);
- finish();
- }
- });
+ mProfileView.setOnClickListener(this::onProfileClick);
bindProfileView();
}
@@ -367,6 +351,19 @@ public class ResolverActivity extends Activity {
+ (categories != null ? Arrays.toString(categories.toArray()) : ""));
}
+ protected void onProfileClick(View v) {
+ final DisplayResolveInfo dri = mAdapter.getOtherProfile();
+ if (dri == null) {
+ return;
+ }
+
+ // Do not show the profile switch message anymore.
+ mProfileSwitchMessageId = -1;
+
+ onTargetSelected(dri, false);
+ finish();
+ }
+
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@@ -445,7 +442,11 @@ public class ResolverActivity extends Activity {
return R.layout.resolver_list;
}
- void bindProfileView() {
+ protected void bindProfileView() {
+ if (mProfileView == null) {
+ return;
+ }
+
final DisplayResolveInfo dri = mAdapter.getOtherProfile();
if (dri != null) {
mProfileView.setVisibility(View.VISIBLE);
@@ -709,9 +710,7 @@ public class ResolverActivity extends Activity {
mRegistered = true;
}
mAdapter.handlePackagesChanged();
- if (mProfileView != null) {
- bindProfileView();
- }
+ bindProfileView();
}
@Override
@@ -1737,9 +1736,7 @@ public class ResolverActivity extends Activity {
@Override
protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
processSortedList(sortedComponents);
- if (mProfileView != null) {
- bindProfileView();
- }
+ bindProfileView();
notifyDataSetChanged();
}
};
@@ -2148,7 +2145,7 @@ public class ResolverActivity extends Activity {
@Override
protected void onPostExecute(Drawable d) {
- if (mProfileView != null && mAdapter.getOtherProfile() == mDisplayResolveInfo) {
+ if (mAdapter.getOtherProfile() == mDisplayResolveInfo) {
bindProfileView();
} else {
mDisplayResolveInfo.setDisplayIcon(d);
diff --git a/core/jni/android_ddm_DdmHandleNativeHeap.cpp b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
index e22f581e14e2..076e99dd1fba 100644
--- a/core/jni/android_ddm_DdmHandleNativeHeap.cpp
+++ b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
@@ -22,6 +22,9 @@
#include <jni.h>
#include "core_jni_helpers.h"
+#include <android-base/logging.h>
+#include <bionic_malloc.h>
+
#include <utils/Log.h>
#include <utils/String8.h>
@@ -30,11 +33,6 @@
#include <sys/types.h>
#include <sys/stat.h>
-extern "C" void get_malloc_leak_info(uint8_t** info, size_t* overallSize,
- size_t* infoSize, size_t* totalMemory, size_t* backtraceSize);
-
-extern "C" void free_malloc_leak_info(uint8_t* info);
-
#define DDMS_HEADER_SIGNATURE 0x812345dd
#define DDMS_VERSION 2
@@ -78,9 +76,16 @@ static jbyteArray DdmHandleNativeHeap_getLeakInfo(JNIEnv* env, jobject) {
ReadFile("/proc/self/maps", maps);
header.mapSize = maps.size();
- uint8_t* allocBytes;
- get_malloc_leak_info(&allocBytes, &header.allocSize, &header.allocInfoSize,
- &header.totalMemory, &header.backtraceSize);
+ android_mallopt_leak_info_t leak_info;
+ if (!android_mallopt(M_GET_MALLOC_LEAK_INFO, &leak_info, sizeof(leak_info))) {
+ PLOG(ERROR) << "*** Failed to get malloc leak info";
+ return nullptr;
+ }
+
+ header.allocSize = leak_info.overall_size;
+ header.allocInfoSize = leak_info.info_size;
+ header.totalMemory = leak_info.total_memory;
+ header.backtraceSize = leak_info.backtrace_size;
ALOGD("*** mapSize: %zu allocSize: %zu allocInfoSize: %zu totalMemory: %zu",
header.mapSize, header.allocSize, header.allocInfoSize, header.totalMemory);
@@ -98,10 +103,10 @@ static jbyteArray DdmHandleNativeHeap_getLeakInfo(JNIEnv* env, jobject) {
env->SetByteArrayRegion(array, sizeof(header),
maps.size(), reinterpret_cast<const jbyte*>(maps.string()));
env->SetByteArrayRegion(array, sizeof(header) + maps.size(),
- header.allocSize, reinterpret_cast<jbyte*>(allocBytes));
+ header.allocSize, reinterpret_cast<jbyte*>(leak_info.buffer));
}
- free_malloc_leak_info(allocBytes);
+ android_mallopt(M_FREE_MALLOC_LEAK_INFO, &leak_info, sizeof(leak_info));
return array;
}
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 195fe58f0beb..69a7c4d80532 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -33,6 +33,8 @@
#include <string>
#include <vector>
+#include <android-base/logging.h>
+#include <bionic_malloc.h>
#include <debuggerd/client.h>
#include <log/log.h>
#include <utils/misc.h>
@@ -663,9 +665,6 @@ static bool openFile(JNIEnv* env, jobject fileDescriptor, UniqueFile& fp)
return true;
}
-/* pulled out of bionic */
-extern "C" void write_malloc_leak_info(FILE* fp);
-
/*
* Dump the native heap, writing human-readable output to the specified
* file descriptor.
@@ -681,8 +680,11 @@ static void android_os_Debug_dumpNativeHeap(JNIEnv* env, jobject,
ALOGD("Native heap dump starting...\n");
// Formatting of the native heap dump is handled by malloc debug itself.
// See https://android.googlesource.com/platform/bionic/+/master/libc/malloc_debug/README.md#backtrace-heap-dump-format
- write_malloc_leak_info(fp.get());
- ALOGD("Native heap dump complete.\n");
+ if (android_mallopt(M_WRITE_MALLOC_LEAK_INFO_TO_FILE, fp.get(), sizeof(FILE*))) {
+ ALOGD("Native heap dump complete.\n");
+ } else {
+ PLOG(ERROR) << "Failed to write native heap dump to file";
+ }
}
/*
diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
index 68c62a6ebf3e..138e24e36753 100644
--- a/core/res/res/layout/chooser_grid.xml
+++ b/core/res/res/layout/chooser_grid.xml
@@ -41,21 +41,6 @@
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true" />
- <TextView android:id="@+id/profile_button"
- android:layout_width="wrap_content"
- android:layout_height="48dp"
- android:layout_marginEnd="8dp"
- android:paddingStart="8dp"
- android:paddingEnd="8dp"
- android:visibility="gone"
- style="?attr/borderlessButtonStyle"
- android:textAppearance="?attr/textAppearanceButton"
- android:textColor="?attr/colorAccent"
- android:gravity="center_vertical"
- android:layout_below="@id/drag"
- android:layout_alignParentRight="true"
- android:singleLine="true"/>
-
<TextView android:id="@+id/title"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
@@ -67,7 +52,7 @@
android:paddingBottom="@dimen/chooser_view_spacing"
android:paddingLeft="24dp"
android:paddingRight="24dp"
- android:layout_below="@id/profile_button"
+ android:layout_below="@id/drag"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
diff --git a/core/res/res/layout/chooser_profile_row.xml b/core/res/res/layout/chooser_profile_row.xml
new file mode 100644
index 000000000000..1a24a073a122
--- /dev/null
+++ b/core/res/res/layout/chooser_profile_row.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center">
+ <TextView
+ android:id="@+id/profile_button"
+ android:layout_width="wrap_content"
+ android:layout_height="48dp"
+ style="?attr/borderlessButtonStyle"
+ android:textAppearance="?attr/textAppearanceButton"
+ android:textColor="?attr/colorAccent"
+ android:singleLine="true"/>
+</LinearLayout>
+
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/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a6a0c6e50a85..2f34c943bdfa 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2794,6 +2794,7 @@
<java-symbol type="drawable" name="scroll_indicator_material" />
<java-symbol type="layout" name="chooser_row" />
+ <java-symbol type="layout" name="chooser_profile_row" />
<java-symbol type="color" name="chooser_row_divider" />
<java-symbol type="layout" name="chooser_row_direct_share" />
<java-symbol type="bool" name="config_supportDoubleTapWake" />
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/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 29e94e8b4bf6..767ec0e38a86 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -18,6 +18,7 @@ package com.android.internal.app;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
@@ -245,7 +246,7 @@ public class ChooserActivityTest {
waitForIdle();
assertThat(activity.getAdapter().getCount(), is(2));
- onView(withId(R.id.profile_button)).check(matches(not(isDisplayed())));
+ onView(withId(R.id.profile_button)).check(doesNotExist());
ResolveInfo[] chosen = new ResolveInfo[1];
sOverrides.onSafelyStartCallback = targetInfo -> {
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/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index eca39262dfb5..2e9b03c6b31e 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -383,7 +383,7 @@ public class CarrierTextController {
}
if (TextUtils.isEmpty(displayText) && !airplaneMode) {
- displayText = TextUtils.join(mSeparator, carrierNames);
+ displayText = joinNotEmpty(mSeparator, carrierNames);
}
final CarrierTextCallbackInfo info = new CarrierTextCallbackInfo(
displayText,
@@ -546,6 +546,25 @@ public class CarrierTextController {
}
}
+ /**
+ * Joins the strings in a sequence using a separator. Empty strings are discarded with no extra
+ * separator added so there are no extra separators that are not needed.
+ */
+ private static CharSequence joinNotEmpty(CharSequence separator, CharSequence[] sequences) {
+ int length = sequences.length;
+ if (length == 0) return "";
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < length; i++) {
+ if (!TextUtils.isEmpty(sequences[i])) {
+ if (!TextUtils.isEmpty(sb)) {
+ sb.append(separator);
+ }
+ sb.append(sequences[i]);
+ }
+ }
+ return sb.toString();
+ }
+
private static List<CharSequence> append(List<CharSequence> list, CharSequence string) {
if (!TextUtils.isEmpty(string)) {
list.add(string);
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/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index a381bbc47657..3f33ba633d77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -3926,6 +3926,10 @@ public class StatusBar extends SystemUI implements DemoMode,
mScrimController.setWakeLockScreenSensorActive(true);
}
+ if (reason == DozeLog.PULSE_REASON_DOCKING && mStatusBarWindow != null) {
+ mStatusBarWindow.suppressWakeUpGesture(true);
+ }
+
boolean passiveAuthInterrupt = reason == DozeLog.PULSE_REASON_NOTIFICATION;
// Set the state to pulsing, so ScrimController will know what to do once we ask it to
// execute the transition. The pulse callback will then be invoked when the scrims
@@ -3945,6 +3949,9 @@ public class StatusBar extends SystemUI implements DemoMode,
callback.onPulseFinished();
updateNotificationPanelTouchState();
mScrimController.setWakeLockScreenSensorActive(false);
+ if (mStatusBarWindow != null) {
+ mStatusBarWindow.suppressWakeUpGesture(false);
+ }
setPulsing(false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 28db28c7a845..44996acafc63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -107,12 +107,13 @@ public class StatusBarWindowView extends FrameLayout {
private boolean mTouchActive;
private boolean mExpandAnimationRunning;
private boolean mExpandAnimationPending;
+ private boolean mSuppressingWakeUpGesture;
private final GestureDetector.SimpleOnGestureListener mGestureListener =
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
- if (mSingleTapEnabled) {
+ if (mSingleTapEnabled && !mSuppressingWakeUpGesture) {
mService.wakeUpIfDozing(SystemClock.uptimeMillis(), StatusBarWindowView.this,
"SINGLE_TAP");
return true;
@@ -327,6 +328,10 @@ public class StatusBarWindowView extends FrameLayout {
mTouchActive = touchActive;
}
+ void suppressWakeUpGesture(boolean suppress) {
+ mSuppressingWakeUpGesture = suppress;
+ }
+
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean isDown = ev.getActionMasked() == MotionEvent.ACTION_DOWN;
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/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index df534d79f730..9f91a17e846d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -104,7 +104,8 @@ public class CarrierTextControllerTest extends SysuiTestCase {
mCarrierTextCallbackInfo = new CarrierTextController.CarrierTextCallbackInfo("",
new CharSequence[]{}, false, new int[]{});
- when(mTelephonyManager.getPhoneCount()).thenReturn(2);
+ when(mTelephonyManager.getPhoneCount()).thenReturn(3);
+
mCarrierTextController = new TestCarrierTextController(mContext, SEPARATOR, true, true,
mKeyguardUpdateMonitor);
// This should not start listening on any of the real dependencies
@@ -130,6 +131,12 @@ public class CarrierTextControllerTest extends SysuiTestCase {
reset(mCarrierTextCallback);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(
new ArrayList<>());
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
+ when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(
+ new ArrayList<>());
+
when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
IccCardConstants.State.CARD_IO_ERROR);
// This should not produce an out of bounds error, even though there are no subscriptions
@@ -173,7 +180,11 @@ public class CarrierTextControllerTest extends SysuiTestCase {
list.add(TEST_SUBSCRIPTION);
when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
+
mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
@@ -197,7 +208,11 @@ public class CarrierTextControllerTest extends SysuiTestCase {
list.add(TEST_SUBSCRIPTION_ROAMING);
when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
+
mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
@@ -219,6 +234,12 @@ public class CarrierTextControllerTest extends SysuiTestCase {
reset(mCarrierTextCallback);
when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(
new ArrayList<>());
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
+ when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(
+ new ArrayList<>());
+
ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
ArgumentCaptor.forClass(
CarrierTextController.CarrierTextCallbackInfo.class);
@@ -233,6 +254,121 @@ public class CarrierTextControllerTest extends SysuiTestCase {
}
+ @Test
+ public void testCarrierText_twoValidSubscriptions() {
+ reset(mCarrierTextCallback);
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
+ when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
+ when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
+
+ mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+ ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextController.CarrierTextCallbackInfo.class);
+
+ mCarrierTextController.updateCarrierText();
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+
+ assertEquals(TEST_CARRIER + SEPARATOR + TEST_CARRIER,
+ captor.getValue().carrierText);
+ }
+
+ @Test
+ public void testCarrierText_oneDisabledSub() {
+ reset(mCarrierTextCallback);
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSimState(anyInt()))
+ .thenReturn(IccCardConstants.State.READY)
+ .thenReturn(IccCardConstants.State.NOT_READY);
+ when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
+ when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
+
+ mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+ ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextController.CarrierTextCallbackInfo.class);
+
+ mCarrierTextController.updateCarrierText();
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+
+ assertEquals(TEST_CARRIER,
+ captor.getValue().carrierText);
+ }
+
+ @Test
+ public void testCarrierText_firstDisabledSub() {
+ reset(mCarrierTextCallback);
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSimState(anyInt()))
+ .thenReturn(IccCardConstants.State.NOT_READY)
+ .thenReturn(IccCardConstants.State.READY);
+ when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
+ when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
+
+ mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+ ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextController.CarrierTextCallbackInfo.class);
+
+ mCarrierTextController.updateCarrierText();
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+
+ assertEquals(TEST_CARRIER,
+ captor.getValue().carrierText);
+ }
+
+ @Test
+ public void testCarrierText_threeSubsMiddleDisabled() {
+ reset(mCarrierTextCallback);
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ list.add(TEST_SUBSCRIPTION);
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSimState(anyInt()))
+ .thenReturn(IccCardConstants.State.READY)
+ .thenReturn(IccCardConstants.State.NOT_READY)
+ .thenReturn(IccCardConstants.State.READY);
+ when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+ mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+ // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
+ // same answer as KeyguardUpdateMonitor. Remove when this is addressed
+ when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
+
+ ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextController.CarrierTextCallbackInfo.class);
+
+ mCarrierTextController.updateCarrierText();
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+
+ assertEquals(TEST_CARRIER + SEPARATOR + TEST_CARRIER,
+ captor.getValue().carrierText);
+ }
+
public static class TestCarrierTextController extends CarrierTextController {
private KeyguardUpdateMonitor mKUM;
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/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 43bc21b1943f..fb16465d3486 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -681,6 +681,25 @@ public class StatusBarTest extends SysuiTestCase {
}
@Test
+ public void testPulseWhileDozingWithDockingReason_suppressWakeUpGesture() {
+ // Keep track of callback to be able to stop the pulse
+ final DozeHost.PulseCallback[] pulseCallback = new DozeHost.PulseCallback[1];
+ doAnswer(invocation -> {
+ pulseCallback[0] = invocation.getArgument(0);
+ return null;
+ }).when(mDozeScrimController).pulse(any(), anyInt());
+
+ // Starting a pulse while docking should suppress wakeup gesture
+ mStatusBar.mDozeServiceHost.pulseWhileDozing(mock(DozeHost.PulseCallback.class),
+ DozeLog.PULSE_REASON_DOCKING);
+ verify(mStatusBarWindowView).suppressWakeUpGesture(eq(true));
+
+ // Ending a pulse should restore wakeup gesture
+ pulseCallback[0].onPulseFinished();
+ verify(mStatusBarWindowView).suppressWakeUpGesture(eq(false));
+ }
+
+ @Test
public void testSetState_changesIsFullScreenUserSwitcherState() {
mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
assertFalse(mStatusBar.isFullScreenUserSwitcherState());
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
index 55a062187bb1..ecea251cc1ac 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
@@ -16,7 +16,9 @@
package com.android.server.contentsuggestions;
+import static android.Manifest.permission.BIND_CONTENT_SUGGESTIONS_SERVICE;
import static android.Manifest.permission.MANAGE_CONTENT_SUGGESTIONS;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -92,16 +94,11 @@ public class ContentSuggestionsManagerService extends
return MAX_TEMP_SERVICE_DURATION_MS;
}
- private boolean isCallerRecents(int userId) {
- if (mServiceNameResolver.isTemporary(userId)) {
- // If a temporary service is set then skip the recents check
- return true;
- }
- return mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid());
- }
-
- private void enforceCallerIsRecents(int userId, String func) {
- if (isCallerRecents(userId)) {
+ private void enforceCaller(int userId, String func) {
+ Context ctx = getContext();
+ if (ctx.checkCallingPermission(BIND_CONTENT_SUGGESTIONS_SERVICE) == PERMISSION_GRANTED
+ || mServiceNameResolver.isTemporary(userId)
+ || mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid())) {
return;
}
@@ -122,7 +119,7 @@ public class ContentSuggestionsManagerService extends
if (imageContextRequestExtras == null) {
throw new IllegalArgumentException("Expected non-null imageContextRequestExtras");
}
- enforceCallerIsRecents(UserHandle.getCallingUserId(), "provideContextImage");
+ enforceCaller(UserHandle.getCallingUserId(), "provideContextImage");
synchronized (mLock) {
final ContentSuggestionsPerUserService service = getServiceForUserLocked(userId);
@@ -141,7 +138,7 @@ public class ContentSuggestionsManagerService extends
int userId,
@NonNull SelectionsRequest selectionsRequest,
@NonNull ISelectionsCallback selectionsCallback) {
- enforceCallerIsRecents(UserHandle.getCallingUserId(), "suggestContentSelections");
+ enforceCaller(UserHandle.getCallingUserId(), "suggestContentSelections");
synchronized (mLock) {
final ContentSuggestionsPerUserService service = getServiceForUserLocked(userId);
@@ -160,7 +157,7 @@ public class ContentSuggestionsManagerService extends
int userId,
@NonNull ClassificationsRequest classificationsRequest,
@NonNull IClassificationsCallback callback) {
- enforceCallerIsRecents(UserHandle.getCallingUserId(), "classifyContentSelections");
+ enforceCaller(UserHandle.getCallingUserId(), "classifyContentSelections");
synchronized (mLock) {
final ContentSuggestionsPerUserService service = getServiceForUserLocked(userId);
@@ -177,7 +174,7 @@ public class ContentSuggestionsManagerService extends
@Override
public void notifyInteraction(
int userId, @NonNull String requestId, @NonNull Bundle bundle) {
- enforceCallerIsRecents(UserHandle.getCallingUserId(), "notifyInteraction");
+ enforceCaller(UserHandle.getCallingUserId(), "notifyInteraction");
synchronized (mLock) {
final ContentSuggestionsPerUserService service = getServiceForUserLocked(userId);
@@ -194,7 +191,7 @@ public class ContentSuggestionsManagerService extends
@Override
public void isEnabled(int userId, @NonNull IResultReceiver receiver)
throws RemoteException {
- enforceCallerIsRecents(UserHandle.getCallingUserId(), "isEnabled");
+ enforceCaller(UserHandle.getCallingUserId(), "isEnabled");
boolean isDisabled;
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d30a9d2b158e..2d00f298e25e 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -508,13 +508,14 @@ public class AudioService extends IAudioService.Stub
// Used to play ringtones outside system_server
private volatile IRingtonePlayer mRingtonePlayer;
- // Devices for which the volume is fixed and VolumePanel slider should be disabled
+ // Devices for which the volume is fixed (volume is either max or muted)
int mFixedVolumeDevices = AudioSystem.DEVICE_OUT_HDMI |
AudioSystem.DEVICE_OUT_DGTL_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_ANLG_DOCK_HEADSET |
AudioSystem.DEVICE_OUT_HDMI_ARC |
AudioSystem.DEVICE_OUT_SPDIF |
AudioSystem.DEVICE_OUT_AUX_LINE;
+ // Devices for which the volume is always max, no volume panel
int mFullVolumeDevices = 0;
private final boolean mMonitorRotation;
@@ -859,6 +860,11 @@ public class AudioService extends IAudioService.Stub
mFixedVolumeDevices &= ~AudioSystem.DEVICE_ALL_HDMI_SYSTEM_AUDIO_AND_SPEAKER;
}
mHdmiPlaybackClient = mHdmiManager.getPlaybackClient();
+ if (mHdmiPlaybackClient != null) {
+ // not a television: HDMI output will be always at max
+ mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
+ mFullVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
+ }
mHdmiCecSink = false;
mHdmiAudioSystemClient = mHdmiManager.getAudioSystemClient();
}
@@ -1065,7 +1071,6 @@ public class AudioService extends IAudioService.Stub
}
if (isPlatformTelevision()) {
- mFixedVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
checkAllFixedVolumeDevices();
synchronized (mHdmiClientLock) {
if (mHdmiManager != null && mHdmiPlaybackClient != null) {
@@ -1656,7 +1661,7 @@ public class AudioService extends IAudioService.Stub
flags &= ~AudioManager.FLAG_FIXED_VOLUME;
if ((streamTypeAlias == AudioSystem.STREAM_MUSIC) &&
- ((device & mFixedVolumeDevices) != 0)) {
+ ((device & mFixedVolumeDevices) != 0)) {
flags |= AudioManager.FLAG_FIXED_VOLUME;
// Always toggle between max safe volume and 0 for fixed volume devices where safe
@@ -1733,8 +1738,9 @@ public class AudioService extends IAudioService.Stub
!checkSafeMediaVolume(streamTypeAlias, aliasIndex + step, device)) {
Log.e(TAG, "adjustStreamVolume() safe volume index = " + oldIndex);
mVolumeController.postDisplaySafeVolumeWarning(flags);
- } else if (streamState.adjustIndex(direction * step, device, caller)
- || streamState.mIsMuted) {
+ } else if (((device & mFullVolumeDevices) == 0)
+ && (streamState.adjustIndex(direction * step, device, caller)
+ || streamState.mIsMuted)) {
// Post message to set system volume (it in turn will post a
// message to persist).
if (streamState.mIsMuted) {
@@ -1785,9 +1791,10 @@ public class AudioService extends IAudioService.Stub
synchronized (mHdmiClientLock) {
if (mHdmiManager != null) {
// mHdmiCecSink true => mHdmiPlaybackClient != null
- if (mHdmiCecSink &&
- streamTypeAlias == AudioSystem.STREAM_MUSIC &&
- oldIndex != newIndex) {
+ if (mHdmiCecSink
+ && streamTypeAlias == AudioSystem.STREAM_MUSIC
+ // vol change on a full volume device
+ && ((device & mFullVolumeDevices) != 0)) {
int keyCode = (direction == -1) ? KeyEvent.KEYCODE_VOLUME_DOWN :
KeyEvent.KEYCODE_VOLUME_UP;
final long ident = Binder.clearCallingIdentity();
@@ -1814,7 +1821,7 @@ public class AudioService extends IAudioService.Stub
}
}
int index = mStreamStates[streamType].getIndex(device);
- sendVolumeUpdate(streamType, oldIndex, index, flags);
+ sendVolumeUpdate(streamType, oldIndex, index, flags, device);
}
// Called after a delay when volume down is pressed while muted
@@ -1824,7 +1831,7 @@ public class AudioService extends IAudioService.Stub
final int device = getDeviceForStream(stream);
final int index = mStreamStates[stream].getIndex(device);
- sendVolumeUpdate(stream, index, index, flags);
+ sendVolumeUpdate(stream, index, index, flags, device);
}
private void setSystemAudioVolume(int oldVolume, int newVolume, int maxVolume, int flags) {
@@ -1835,7 +1842,9 @@ public class AudioService extends IAudioService.Stub
|| mHdmiTvClient == null
|| oldVolume == newVolume
|| (flags & AudioManager.FLAG_HDMI_SYSTEM_AUDIO_VOLUME) != 0
- || !mHdmiSystemAudioSupported) return;
+ || !mHdmiSystemAudioSupported) {
+ return;
+ }
final long token = Binder.clearCallingIdentity();
try {
mHdmiTvClient.setSystemAudioVolume(oldVolume, newVolume, maxVolume);
@@ -2149,7 +2158,7 @@ public class AudioService extends IAudioService.Stub
Binder.restoreCallingIdentity(identity);
}
}
- sendVolumeUpdate(streamType, oldIndex, index, flags);
+ sendVolumeUpdate(streamType, oldIndex, index, flags, device);
}
@@ -2303,18 +2312,22 @@ public class AudioService extends IAudioService.Stub
}
// UI update and Broadcast Intent
- protected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
+ protected void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags, int device)
+ {
streamType = mStreamVolumeAlias[streamType];
if (streamType == AudioSystem.STREAM_MUSIC) {
- flags = updateFlagsForSystemAudio(flags);
+ flags = updateFlagsForTvPlatform(flags);
+ if ((device & mFullVolumeDevices) != 0) {
+ flags &= ~AudioManager.FLAG_SHOW_UI;
+ }
}
mVolumeController.postVolumeChanged(streamType, flags);
}
// If Hdmi-CEC system audio mode is on, we show volume bar only when TV
// receives volume notification from Audio Receiver.
- private int updateFlagsForSystemAudio(int flags) {
+ private int updateFlagsForTvPlatform(int flags) {
synchronized (mHdmiClientLock) {
if (mHdmiTvClient != null) {
if (mHdmiSystemAudioSupported &&
@@ -2328,7 +2341,7 @@ public class AudioService extends IAudioService.Stub
// UI update and Broadcast Intent
private void sendMasterMuteUpdate(boolean muted, int flags) {
- mVolumeController.postMasterMuteChanged(updateFlagsForSystemAudio(flags));
+ mVolumeController.postMasterMuteChanged(updateFlagsForTvPlatform(flags));
broadcastMasterMuteStatus(muted);
}
@@ -2355,6 +2368,9 @@ public class AudioService extends IAudioService.Stub
int device,
boolean force,
String caller) {
+ if ((device & mFullVolumeDevices) != 0) {
+ return;
+ }
VolumeStreamState streamState = mStreamStates[streamType];
if (streamState.setIndex(index, device, caller) || force) {
@@ -5810,9 +5826,14 @@ public class AudioService extends IAudioService.Stub
}
//==========================================================================================
- // Hdmi Cec system audio mode.
- // If Hdmi Cec's system audio mode is on, audio service should send the volume change
- // to HdmiControlService so that the audio receiver can handle it.
+ // Hdmi CEC:
+ // - System audio mode:
+ // If Hdmi Cec's system audio mode is on, audio service should send the volume change
+ // to HdmiControlService so that the audio receiver can handle it.
+ // - CEC sink:
+ // OUT_HDMI becomes a "full volume device", i.e. output is always at maximum level
+ // and volume changes won't be taken into account on this device. Volume adjustments
+ // are transformed into key events for the HDMI playback client.
//==========================================================================================
private class MyDisplayStatusCallback implements HdmiPlaybackClient.DisplayStatusCallback {
@@ -5821,8 +5842,18 @@ public class AudioService extends IAudioService.Stub
if (mHdmiManager != null) {
mHdmiCecSink = (status != HdmiControlManager.POWER_STATUS_UNKNOWN);
// Television devices without CEC service apply software volume on HDMI output
- if (isPlatformTelevision() && !mHdmiCecSink) {
- mFixedVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
+ if (mHdmiCecSink) {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "CEC sink: setting HDMI as full vol device");
+ }
+ mFullVolumeDevices |= AudioSystem.DEVICE_OUT_HDMI;
+ } else {
+ if (DEBUG_VOL) {
+ Log.d(TAG, "TV, no CEC: setting HDMI as regular vol device");
+ }
+ // Android TV devices without CEC service apply software volume on
+ // HDMI output
+ mFullVolumeDevices &= ~AudioSystem.DEVICE_OUT_HDMI;
}
checkAllFixedVolumeDevices();
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 3e3a4f2fde6c..e5ecd49c67da 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -308,8 +308,7 @@ public class NotificationManagerService extends SystemService {
static final String[] DEFAULT_ALLOWED_ADJUSTMENTS = new String[] {
Adjustment.KEY_IMPORTANCE,
Adjustment.KEY_CONTEXTUAL_ACTIONS,
- Adjustment.KEY_TEXT_REPLIES,
- Adjustment.KEY_USER_SENTIMENT};
+ Adjustment.KEY_TEXT_REPLIES};
static final String[] NON_BLOCKABLE_DEFAULT_ROLES = new String[] {
RoleManager.ROLE_DIALER,
@@ -7324,7 +7323,7 @@ public class NotificationManagerService extends SystemService {
private static final String ATT_USER_SET = "user_set";
// TODO: STOPSHIP (b/127994217) switch to final value when onboarding flow is implemented
- private static final String TAG_ALLOWED_ADJUSTMENT_TYPES = "allowed_adjustments_tmp";
+ private static final String TAG_ALLOWED_ADJUSTMENT_TYPES = "allowed_adjustments_tmp2";
private static final String ATT_TYPES = "types";
private final Object mLock = new Object();
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);
}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 0caeb10177b7..1edb93a0cdb9 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -2563,9 +2563,8 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
private static final class ThermalEventListener extends IThermalEventListener.Stub {
@Override
public void notifyThrottling(Temperature temp) {
- StatsLog.write(StatsLog.THERMAL_THROTTLING, temp.getType(),
- StatsLog.THERMAL_THROTTLING_STATE_CHANGED__STATE__UNKNOWN,
- temp.getValue(), temp.getStatus(), temp.getName());
+ StatsLog.write(StatsLog.THERMAL_THROTTLING_SEVERITY_STATE_CHANGED, temp.getType(),
+ temp.getName(), (int) (temp.getValue() * 10), temp.getStatus());
}
}