Merge "Call WindowContainer#dump in all levels" into rvc-dev
diff --git a/apex/blobstore/framework/java/android/app/blob/BlobInfo.java b/apex/blobstore/framework/java/android/app/blob/BlobInfo.java
index 80062d5..ba92d95 100644
--- a/apex/blobstore/framework/java/android/app/blob/BlobInfo.java
+++ b/apex/blobstore/framework/java/android/app/blob/BlobInfo.java
@@ -16,9 +16,13 @@
package android.app.blob;
+import static android.text.format.Formatter.FLAG_IEC_UNITS;
+
import android.annotation.NonNull;
+import android.app.AppGlobals;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.format.Formatter;
import java.util.Collections;
import java.util.List;
@@ -32,13 +36,15 @@
private final long mId;
private final long mExpiryTimeMs;
private final CharSequence mLabel;
+ private final long mSizeBytes;
private final List<LeaseInfo> mLeaseInfos;
- public BlobInfo(long id, long expiryTimeMs, CharSequence label,
+ public BlobInfo(long id, long expiryTimeMs, CharSequence label, long sizeBytes,
List<LeaseInfo> leaseInfos) {
mId = id;
mExpiryTimeMs = expiryTimeMs;
mLabel = label;
+ mSizeBytes = sizeBytes;
mLeaseInfos = leaseInfos;
}
@@ -46,6 +52,7 @@
mId = in.readLong();
mExpiryTimeMs = in.readLong();
mLabel = in.readCharSequence();
+ mSizeBytes = in.readLong();
mLeaseInfos = in.readArrayList(null /* classloader */);
}
@@ -61,6 +68,10 @@
return mLabel;
}
+ public long getSizeBytes() {
+ return mSizeBytes;
+ }
+
public List<LeaseInfo> getLeases() {
return Collections.unmodifiableList(mLeaseInfos);
}
@@ -70,6 +81,7 @@
dest.writeLong(mId);
dest.writeLong(mExpiryTimeMs);
dest.writeCharSequence(mLabel);
+ dest.writeLong(mSizeBytes);
dest.writeList(mLeaseInfos);
}
@@ -83,10 +95,16 @@
+ "id: " + mId + ","
+ "expiryMs: " + mExpiryTimeMs + ","
+ "label: " + mLabel + ","
+ + "size: " + formatBlobSize(mSizeBytes) + ","
+ "leases: " + LeaseInfo.toShortString(mLeaseInfos) + ","
+ "}";
}
+ private static String formatBlobSize(long sizeBytes) {
+ return Formatter.formatFileSize(AppGlobals.getInitialApplication(),
+ sizeBytes, FLAG_IEC_UNITS);
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
index 8fff0d9..0a5ada2 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -482,7 +482,8 @@
descriptionResId, leasee.description));
});
blobInfos.add(new BlobInfo(blobMetadata.getBlobId(),
- blobHandle.getExpiryTimeMillis(), blobHandle.getLabel(), leaseInfos));
+ blobHandle.getExpiryTimeMillis(), blobHandle.getLabel(),
+ blobMetadata.getSize(), leaseInfos));
});
}
return blobInfos;
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index 7cbb98e..19f578e 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -203,6 +203,15 @@
/** Returned by {@link #getDurationMicros()} when the duration is unknown. */
public static final int UNKNOWN_DURATION = Integer.MIN_VALUE;
+ /**
+ * For each {@link #getSeekPoints} call, returns a single {@link SeekPoint} whose {@link
+ * SeekPoint#timeMicros} matches the requested timestamp, and whose {@link
+ * SeekPoint#position} is 0.
+ *
+ * @hide
+ */
+ public static final SeekMap DUMMY = new SeekMap(new DummyExoPlayerSeekMap());
+
private final com.google.android.exoplayer2.extractor.SeekMap mExoPlayerSeekMap;
private SeekMap(com.google.android.exoplayer2.extractor.SeekMap exoplayerSeekMap) {
@@ -795,6 +804,18 @@
*/
public static final String PARAMETER_EAGERLY_EXPOSE_TRACKTYPE =
"android.media.mediaparser.eagerlyExposeTrackType";
+ /**
+ * Sets whether a dummy {@link SeekMap} should be exposed before starting extraction. {@code
+ * boolean} expected. Default value is {@code false}.
+ *
+ * <p>For each {@link SeekMap#getSeekPoints} call, the dummy {@link SeekMap} returns a single
+ * {@link SeekPoint} whose {@link SeekPoint#timeMicros} matches the requested timestamp, and
+ * whose {@link SeekPoint#position} is 0.
+ *
+ * @hide
+ */
+ public static final String PARAMETER_EXPOSE_DUMMY_SEEKMAP =
+ "android.media.mediaparser.exposeDummySeekMap";
// Private constants.
@@ -958,6 +979,7 @@
private boolean mIncludeSupplementalData;
private boolean mIgnoreTimestampOffset;
private boolean mEagerlyExposeTrackType;
+ private boolean mExposeDummySeekMap;
private String mParserName;
private Extractor mExtractor;
private ExtractorInput mExtractorInput;
@@ -1017,6 +1039,9 @@
if (PARAMETER_EAGERLY_EXPOSE_TRACKTYPE.equals(parameterName)) {
mEagerlyExposeTrackType = (boolean) value;
}
+ if (PARAMETER_EXPOSE_DUMMY_SEEKMAP.equals(parameterName)) {
+ mExposeDummySeekMap = (boolean) value;
+ }
mParserParameters.put(parameterName, value);
return this;
}
@@ -1078,11 +1103,10 @@
}
mExoDataReader.mInputReader = seekableInputReader;
- // TODO: Apply parameters when creating extractor instances.
if (mExtractor == null) {
+ mPendingExtractorInit = true;
if (!mParserName.equals(PARSER_NAME_UNKNOWN)) {
mExtractor = createExtractor(mParserName);
- mExtractor.init(new ExtractorOutputAdapter());
} else {
for (String parserName : mParserNamesPool) {
Extractor extractor = createExtractor(parserName);
@@ -1107,9 +1131,18 @@
}
if (mPendingExtractorInit) {
+ if (mExposeDummySeekMap) {
+ // We propagate the dummy seek map before initializing the extractor, in case the
+ // extractor initialization outputs a seek map.
+ mOutputConsumer.onSeekMapFound(SeekMap.DUMMY);
+ }
mExtractor.init(new ExtractorOutputAdapter());
mPendingExtractorInit = false;
+ // We return after initialization to allow clients use any output information before
+ // starting actual extraction.
+ return true;
}
+
if (isPendingSeek()) {
mExtractor.seek(mPendingSeekPosition, mPendingSeekTimeMicros);
removePendingSeek();
@@ -1683,6 +1716,28 @@
}
}
+ private static final class DummyExoPlayerSeekMap
+ implements com.google.android.exoplayer2.extractor.SeekMap {
+
+ @Override
+ public boolean isSeekable() {
+ return true;
+ }
+
+ @Override
+ public long getDurationUs() {
+ return C.TIME_UNSET;
+ }
+
+ @Override
+ public SeekPoints getSeekPoints(long timeUs) {
+ com.google.android.exoplayer2.extractor.SeekPoint seekPoint =
+ new com.google.android.exoplayer2.extractor.SeekPoint(
+ timeUs, /* position= */ 0);
+ return new SeekPoints(seekPoint, seekPoint);
+ }
+ }
+
/** Creates extractor instances. */
private interface ExtractorFactory {
@@ -1923,6 +1978,7 @@
expectedTypeByParameterName.put(PARAMETER_INCLUDE_SUPPLEMENTAL_DATA, Boolean.class);
expectedTypeByParameterName.put(PARAMETER_IGNORE_TIMESTAMP_OFFSET, Boolean.class);
expectedTypeByParameterName.put(PARAMETER_EAGERLY_EXPOSE_TRACKTYPE, Boolean.class);
+ expectedTypeByParameterName.put(PARAMETER_EXPOSE_DUMMY_SEEKMAP, Boolean.class);
EXPECTED_TYPE_BY_PARAMETER_NAME = Collections.unmodifiableMap(expectedTypeByParameterName);
}
}
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 2216633..414b53d 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -450,13 +450,28 @@
TvCasSessionOpenStatus tv_cas_session_open_status =
280 [(module) = "framework"];
AssistantInvocationReported assistant_invocation_reported = 281 [(module) = "framework"];
+ DisplayWakeReported display_wake_reported = 282 [(module) = "framework"];
+ CarUserHalModifyUserRequestReported car_user_hal_modify_user_request_reported =
+ 283 [(module) = "car"];
+ CarUserHalModifyUserResponseReported car_user_hal_modify_user_response_reported =
+ 284 [(module) = "car"];
+ CarUserHalPostSwitchResponseReported car_user_hal_post_switch_response_reported =
+ 285 [(module) = "car"];
+ CarUserHalInitialUserInfoRequestReported car_user_hal_initial_user_info_request_reported =
+ 286 [(module) = "car"];
+ CarUserHalInitialUserInfoResponseReported car_user_hal_initial_user_info_response_reported =
+ 287 [(module) = "car"];
+ CarUserHalUserAssociationRequestReported car_user_hal_user_association_request_reported =
+ 288 [(module) = "car"];
+ CarUserHalSetUserAssociationResponseReported car_user_hal_set_user_association_response_reported =
+ 289 [(module) = "car"];
// StatsdStats tracks platform atoms with ids upto 500.
// Update StatsdStats::kMaxPushedAtomId when atom ids here approach that value.
}
// Pulled events will start at field 10000.
- // Next: 10084
+ // Next: 10081
oneof pulled {
WifiBytesTransfer wifi_bytes_transfer = 10000 [(module) = "framework"];
WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001 [(module) = "framework"];
@@ -547,10 +562,11 @@
SimSlotState sim_slot_state = 10078 [(module) = "telephony"];
SupportedRadioAccessFamily supported_radio_access_family = 10079 [(module) = "telephony"];
SettingSnapshot setting_snapshot = 10080 [(module) = "framework"];
- DisplayWakeReason display_wake_reason = 10081 [(module) = "framework"];
+ //10081 free for use
DataUsageBytesTransfer data_usage_bytes_transfer = 10082 [(module) = "framework"];
BytesTransferByTagAndMetered bytes_transfer_by_tag_and_metered =
10083 [(module) = "framework"];
+ DNDModeProto dnd_mode_rule = 10084 [(module) = "framework"];
}
// DO NOT USE field numbers above 100,000 in AOSP.
@@ -6068,6 +6084,76 @@
}
/**
+ * Atom that represents an item in the list of Do Not Disturb rules, pulled from
+ * NotificationManagerService.java.
+ */
+message DNDModeProto {
+ enum Mode {
+ ROOT_CONFIG = -1; // Used to distinguish the config (one per user) from the rules.
+ ZEN_MODE_OFF = 0;
+ ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1;
+ ZEN_MODE_NO_INTERRUPTIONS = 2;
+ ZEN_MODE_ALARMS = 3;
+ }
+ optional int32 user = 1; // Android user ID (0, 1, 10, ...)
+ optional bool enabled = 2; // true for ROOT_CONFIG if a manualRule is enabled
+ optional bool channels_bypassing = 3; // only valid for ROOT_CONFIG
+ optional Mode zen_mode = 4;
+ // id is one of the system default rule IDs, or empty
+ // May also be "MANUAL_RULE" to indicate app-activation of the manual rule.
+ optional string id = 5;
+ optional int32 uid = 6 [(is_uid) = true]; // currently only SYSTEM_UID or 0 for other
+ optional DNDPolicyProto policy = 7;
+}
+
+/**
+ * Atom that represents a Do Not Disturb policy, an optional detail proto for DNDModeProto.
+ */
+message DNDPolicyProto {
+ enum State {
+ STATE_UNSET = 0;
+ STATE_ALLOW = 1;
+ STATE_DISALLOW = 2;
+ }
+ optional State calls = 1;
+ optional State repeat_callers = 2;
+ optional State messages = 3;
+ optional State conversations = 4;
+ optional State reminders = 5;
+ optional State events = 6;
+ optional State alarms = 7;
+ optional State media = 8;
+ optional State system = 9;
+ optional State fullscreen = 10;
+ optional State lights = 11;
+ optional State peek = 12;
+ optional State status_bar = 13;
+ optional State badge = 14;
+ optional State ambient = 15;
+ optional State notification_list = 16;
+
+ enum PeopleType {
+ PEOPLE_UNSET = 0;
+ PEOPLE_ANYONE = 1;
+ PEOPLE_CONTACTS = 2;
+ PEOPLE_STARRED = 3;
+ PEOPLE_NONE = 4;
+ }
+
+ optional PeopleType allow_calls_from = 17;
+ optional PeopleType allow_messages_from = 18;
+
+ enum ConversationType {
+ CONV_UNSET = 0;
+ CONV_ANYONE = 1;
+ CONV_IMPORTANT = 2;
+ CONV_NONE = 3;
+ }
+
+ optional ConversationType allow_conversations_from = 19;
+}
+
+/**
* Atom that contains a list of a package's channel group preferences, pulled from
* NotificationManagerService.java.
*/
@@ -8001,6 +8087,245 @@
}
/**
+ * Logs when Car User Hal is requested to switch/create/remove user.
+ *
+ * Logged from:
+ * packages/services/Car/service/src/com/android/car/hal/UserHalService.java
+ */
+message CarUserHalModifyUserRequestReported {
+ // Request id for the request.
+ optional int32 request_id = 1;
+ // Request type.
+ enum RequestType {
+ UNKNOWN = 0;
+ // Car user manager requested user switch.
+ SWITCH_REQUEST_ANDROID = 1;
+ // OEM requested User switch.
+ SWITCH_REQUEST_OEM = 2;
+ // Hal switch requested after android switch using activity manager.
+ SWITCH_REQUEST_LEGACY = 3;
+ // Create User
+ CREATE_REQUEST = 4;
+ // Remove User
+ REMOVE_REQUEST = 5;
+ }
+ optional RequestType request_type = 2;
+ // Android User id of the current user which can only be 0, 10, 11 and so on.
+ // -1 if not available.
+ optional int32 user_id = 3;
+ // VHAL flags of the current user. (-1 if not available)
+ optional int32 user_flags = 4;
+ // Android User id of the target user for switch/create/remove. It can only
+ // be 0, 10, 11 and so on. -1 if not available.
+ optional int32 target_user_id = 5;
+ // VHAL flags of the target user for switch/create/remove. (-1 if not available)
+ optional int32 target_user_flags = 6;
+ // Request timeout Milliseconds (-1 if not available)
+ optional int32 timeout_millis = 7;
+}
+
+/**
+ * Logs when Car User Hal responds to switch/create user request.
+ *
+ * Logged from:
+ * packages/services/Car/service/src/com/android/car/hal/UserHalService.java
+ */
+message CarUserHalModifyUserResponseReported {
+ // Request id of the request associated with the response.
+ optional int32 request_id = 1;
+ // Car user hal callback status.
+ enum CallbackStatus {
+ UNKNOWN = 0;
+ // Hal response was invalid.
+ INVALID = 1;
+ // Hal response was ok.
+ OK = 2;
+ // Hal timeout during set call.
+ HAL_SET_TIMEOUT = 3;
+ // Hal response timeout.
+ HAL_RESPONSE_TIMEOUT = 4;
+ // Hal responded with wrong info.
+ WRONG_HAL_RESPONSE = 5;
+ // Hal is processing multiple requests simultaneously.
+ CONCURRENT_OPERATION = 6;
+ }
+ optional CallbackStatus callback_status = 2;
+
+ // Hal request status for user switch/create/remove.
+ enum HalRequestStatus {
+ UNSPECIFIED = 0;
+ // Hal request for user switch/create is successful.
+ SUCCESS = 1;
+ // Hal request for user switch/create failed.
+ FAILURE = 2;
+ }
+ optional HalRequestStatus request_status = 3;
+}
+
+/**
+ * Logs when post switch response is posted to Car User Hal.
+ *
+ * Logged from:
+ * packages/services/Car/service/src/com/android/car/hal/UserHalService.java
+ */
+message CarUserHalPostSwitchResponseReported {
+ // Request id.
+ optional int32 request_id = 1;
+
+ // Android user switch status.
+ enum UserSwitchStatus {
+ UNKNOWN = 0;
+ // Android user switch is successful.
+ SUCCESS = 1;
+ // Android user switch failed.
+ FAILURE = 2;
+ }
+ optional UserSwitchStatus switch_status = 2;
+}
+
+/**
+ * Logs when initial user information is requested from Car User Hal.
+ *
+ * Logged from:
+ * packages/services/Car/service/src/com/android/car/hal/UserHalService.java
+ */
+message CarUserHalInitialUserInfoRequestReported {
+ // Request id for the request.
+ optional int32 request_id = 1;
+
+ // Request type for initial user information.
+ enum InitialUserInfoRequestType {
+ UNKNOWN = 0;
+ // At the first time Android was booted (or after a factory reset).
+ FIRST_BOOT = 1;
+ // At the first time Android was booted after the system was updated.
+ FIRST_BOOT_AFTER_OTA = 2;
+ // When Android was booted "from scratch".
+ COLD_BOOT = 3;
+ // When Android was resumed after the system was suspended to memory.
+ RESUME = 4;
+ }
+ optional InitialUserInfoRequestType request_type = 2;
+ // Request timeout Milliseconds (-1 if not available)
+ optional int32 timeout_millis = 3;
+}
+
+/**
+ * Logs when Car User Hal responds to initial user information requests.
+ *
+ * Logged from:
+ * packages/services/Car/service/src/com/android/car/hal/UserHalService.java
+ */
+message CarUserHalInitialUserInfoResponseReported {
+ // Request id of the request associated with the response.
+ optional int32 request_id = 1;
+ // Car user hal callback status.
+ enum CallbackStatus {
+ UNKNOWN = 0;
+ // Hal response was invalid.
+ INVALID = 1;
+ // Hal response was ok.
+ OK = 2;
+ // Hal timeout during set call.
+ HAL_SET_TIMEOUT = 3;
+ // Hal response timeout.
+ HAL_RESPONSE_TIMEOUT = 4;
+ // Hal responded with wrong info.
+ WRONG_HAL_RESPONSE = 5;
+ // Hal is processing multiple requests simultaneously.
+ CONCURRENT_OPERATION = 6;
+ }
+ optional CallbackStatus callback_status = 2;
+ // Response for initial user information request.
+ enum InitialUserInfoResponseAction {
+ UNSPECIFIED = 0;
+ // Let the Android System decide what to do.
+ DEFAULT = 1;
+ // Switch to an existing Android user.
+ SWITCH = 2;
+ // Create a new Android user (and switch to it).
+ CREATE = 3;
+ }
+ optional InitialUserInfoResponseAction response_action = 3;
+ // Android User id of the target user which can only be 0, 10, 11 and so on.
+ // -1 if not available.
+ optional int32 target_user = 4;
+ // VHAL flags of the current user. (-1 if not available)
+ optional int32 target_user_flags = 5;
+ // User locales
+ optional string user_locales = 6;
+}
+
+/**
+ * Logs when set user association is requested from Car User Hal.
+ *
+ * Logged from:
+ * packages/services/Car/service/src/com/android/car/hal/UserHalService.java
+ */
+message CarUserHalUserAssociationRequestReported {
+ // Request id for the request.
+ optional int32 request_id = 1;
+ // Request type.
+ enum RequestType {
+ UNKNOWN = 0;
+ // For setting user association information.
+ SET = 1;
+ // For getting user association information.
+ GET = 2;
+ }
+ optional RequestType request_type = 2;
+ // Android User id of the current user which can only be 0, 10, 11 and so on.
+ // -1 if not available.
+ optional int32 current_user_id = 3;
+ // VHAL flags of the current user. (-1 if not available)
+ optional int32 current_user_flags = 4;
+ // Number of the set associations requested.
+ optional int32 number_associations = 5;
+ // Concatenated string for the types from set associations request.
+ // This is a string converted from an array of integers.
+ optional string user_identification_association_types = 6;
+ // Concatenated string for the values from set associations request.
+ // This is a string converted from an array of integers.
+ optional string user_identification_association_values = 7;
+}
+
+/**
+ * Logs when Car User Hal responds to set user association requests.
+ *
+ * Logged from:
+ * packages/services/Car/service/src/com/android/car/hal/UserHalService.java
+ */
+message CarUserHalSetUserAssociationResponseReported {
+ // Request id of the request associated with the response.
+ optional int32 request_id = 1;
+ // Car user hal callback status.
+ enum CallbackStatus {
+ UNKNOWN = 0;
+ // Hal response was invalid.
+ INVALID = 1;
+ // Hal response was ok.
+ OK = 2;
+ // Hal timeout during set call.
+ HAL_SET_TIMEOUT = 3;
+ // Hal response timeout.
+ HAL_RESPONSE_TIMEOUT = 4;
+ // Hal responded with wrong info.
+ WRONG_HAL_RESPONSE = 5;
+ // Hal is processing multiple requests simultaneously.
+ CONCURRENT_OPERATION = 6;
+ }
+ optional CallbackStatus callback_status = 2;
+ // Number of the set associations in the response.
+ optional int32 number_associations = 3;
+ // Concatenated string for the types from set associations request.
+ // This is a string converted from an array of integers.
+ optional string user_identification_association_types = 4;
+ // Concatenated string for the values from set associations request.
+ // This is a string converted from an array of integers.
+ optional string user_identification_association_values = 5;
+}
+
+/**
* Logs whether GarageMode is entered.
*
* Logged from:
@@ -9817,15 +10142,20 @@
optional android.stats.accessibility.ServiceStatus service_status = 2;
}
-message DisplayWakeReason {
+/**
+ * Logs when display wake up.
+ *
+ * Logged from:
+ * services/core/java/com/android/server/power/Notifier.java
+ */
+
+message DisplayWakeReported {
// Wake_up_reason code
// If LOWORD(wake_up_reason) = 0
// reference to HIWORD(wake_up_reason) PowerManager.WAKE_REASON_XXX
// else reference wake_up_reason to
- // frameworks/base/services/core/java/com/android/server/power/Notifier.java#DispWakeupReason
+ // services/core/java/com/android/server/power/Notifier.java#onWakeUp
optional int32 wake_up_reason = 1;
- // Count of wake up by reason
- optional int32 wake_times = 2;
}
/**
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 97b704c..b608a34 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -601,20 +601,6 @@
@TestApi
public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 2;
- // TODO: remove this when development is done.
- // These are debug flags used between OomAdjuster and AppOpsService to detect and report absence
- // of the real flags.
- /** @hide */
- public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q = 1 << 27;
- /** @hide */
- public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q = 1 << 28;
- /** @hide */
- public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 29;
- /** @hide */
- public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA = 1 << 30;
- /** @hide */
- public static final int DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 31;
-
/** @hide all capabilities, the ORing of all flags in {@link ProcessCapability}*/
@TestApi
public static final int PROCESS_CAPABILITY_ALL = PROCESS_CAPABILITY_FOREGROUND_LOCATION
@@ -653,29 +639,9 @@
*/
public static void printCapabilitiesFull(PrintWriter pw, @ProcessCapability int caps) {
printCapabilitiesSummary(pw, caps);
- if ((caps & DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) {
- pw.print(" !L");
- }
- if ((caps & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
- pw.print(" !C");
- }
- if ((caps & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q) != 0) {
- pw.print(" !Cq");
- }
- if ((caps & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
- pw.print(" !M");
- }
- if ((caps & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q) != 0) {
- pw.print(" !Mq");
- }
final int remain = caps & ~(PROCESS_CAPABILITY_FOREGROUND_LOCATION
| PROCESS_CAPABILITY_FOREGROUND_CAMERA
- | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
- | DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION
- | DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA
- | DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q
- | DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
- | DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q);
+ | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE);
if (remain != 0) {
pw.print('+');
pw.print(remain);
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index c491eea..a5965bc 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -398,13 +398,6 @@
*/
public abstract boolean isUidCurrentlyInstrumented(int uid);
- /**
- * Show a debug toast, asking user to file a bugreport.
- */
- // TODO: remove this toast after feature development is done
- public abstract void showWhileInUseDebugToast(int uid, int op, int mode);
-
-
/** Is this a device owner app? */
public abstract boolean isDeviceOwner(int uid);
@@ -429,11 +422,17 @@
int userId, int[] appIdWhitelist);
/**
- * Add or delete uid from the ActivityManagerService PendingStartActivityUids list.
+ * Add uid to the ActivityManagerService PendingStartActivityUids list.
* @param uid uid
- * @param pending add to the list if true, delete from list if false.
+ * @param pid pid of the ProcessRecord that is pending top.
*/
- public abstract void updatePendingTopUid(int uid, boolean pending);
+ public abstract void addPendingTopUid(int uid, int pid);
+
+ /**
+ * Delete uid from the ActivityManagerService PendingStartActivityUids list.
+ * @param uid uid
+ */
+ public abstract void deletePendingTopUid(int uid);
/**
* Is the uid in ActivityManagerService PendingStartActivityUids list?
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 108b9ee..812ca4a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -123,6 +123,7 @@
import android.os.TelephonyServiceManager;
import android.os.Trace;
import android.os.UserHandle;
+import android.os.UserManager;
import android.permission.IPermissionManager;
import android.provider.BlockedNumberContract;
import android.provider.CalendarContract;
@@ -6816,7 +6817,11 @@
throw ex.rethrowFromSystemServer();
}
if (holder == null) {
- Slog.e(TAG, "Failed to find provider info for " + auth);
+ if (UserManager.get(c).isUserUnlocked(userId)) {
+ Slog.e(TAG, "Failed to find provider info for " + auth);
+ } else {
+ Slog.w(TAG, "Failed to find provider info for " + auth + " (user not unlocked)");
+ }
return null;
}
diff --git a/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java b/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java
index bea1bd6..b3f9e31 100644
--- a/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java
+++ b/core/java/android/app/contentsuggestions/ContentSuggestionsManager.java
@@ -95,7 +95,7 @@
try {
mService.provideContextBitmap(mUser, bitmap, imageContextRequestExtras);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw e.rethrowFromSystemServer();
}
}
@@ -117,7 +117,7 @@
try {
mService.provideContextImage(mUser, taskId, imageContextRequestExtras);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw e.rethrowFromSystemServer();
}
}
@@ -146,7 +146,7 @@
mService.suggestContentSelections(
mUser, request, new SelectionsCallbackWrapper(callback, callbackExecutor));
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw e.rethrowFromSystemServer();
}
}
@@ -173,7 +173,7 @@
mService.classifyContentSelections(
mUser, request, new ClassificationsCallbackWrapper(callback, callbackExecutor));
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw e.rethrowFromSystemServer();
}
}
@@ -193,7 +193,7 @@
try {
mService.notifyInteraction(mUser, requestId, interaction);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw e.rethrowFromSystemServer();
}
}
@@ -213,9 +213,10 @@
mService.isEnabled(mUser, receiver);
return receiver.getIntResult() != 0;
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw e.rethrowFromSystemServer();
+ } catch (SyncResultReceiver.TimeoutException e) {
+ throw new RuntimeException("Fail to get the enable status.");
}
- return false;
}
/**
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 6d49add..23c8602 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -1072,7 +1072,7 @@
* @param lastFrameNumber last frame number returned from binder.
* @param repeatingRequestTypes the repeating requests' types.
*/
- private void checkEarlyTriggerSequenceComplete(
+ private void checkEarlyTriggerSequenceCompleteLocked(
final int requestId, final long lastFrameNumber,
final int[] repeatingRequestTypes) {
// lastFrameNumber being equal to NO_FRAMES_CAPTURED means that the request
@@ -1212,7 +1212,7 @@
if (repeating) {
if (mRepeatingRequestId != REQUEST_ID_NONE) {
- checkEarlyTriggerSequenceComplete(mRepeatingRequestId,
+ checkEarlyTriggerSequenceCompleteLocked(mRepeatingRequestId,
requestInfo.getLastFrameNumber(),
mRepeatingRequestTypes);
}
@@ -1269,7 +1269,7 @@
return;
}
- checkEarlyTriggerSequenceComplete(requestId, lastFrameNumber, requestTypes);
+ checkEarlyTriggerSequenceCompleteLocked(requestId, lastFrameNumber, requestTypes);
}
}
}
@@ -1302,7 +1302,7 @@
long lastFrameNumber = mRemoteDevice.flush();
if (mRepeatingRequestId != REQUEST_ID_NONE) {
- checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber,
+ checkEarlyTriggerSequenceCompleteLocked(mRepeatingRequestId, lastFrameNumber,
mRepeatingRequestTypes);
mRepeatingRequestId = REQUEST_ID_NONE;
mRepeatingRequestTypes = null;
@@ -1442,78 +1442,135 @@
long completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
long completedReprocessFrameNumber = mFrameNumberTracker.getCompletedReprocessFrameNumber();
long completedZslStillFrameNumber = mFrameNumberTracker.getCompletedZslStillFrameNumber();
- boolean isReprocess = false;
+
Iterator<RequestLastFrameNumbersHolder> iter = mRequestLastFrameNumbersList.iterator();
while (iter.hasNext()) {
final RequestLastFrameNumbersHolder requestLastFrameNumbers = iter.next();
- boolean sequenceCompleted = false;
final int requestId = requestLastFrameNumbers.getRequestId();
final CaptureCallbackHolder holder;
- synchronized(mInterfaceLock) {
- if (mRemoteDevice == null) {
- Log.w(TAG, "Camera closed while checking sequences");
- return;
+ if (mRemoteDevice == null) {
+ Log.w(TAG, "Camera closed while checking sequences");
+ return;
+ }
+ if (!requestLastFrameNumbers.isSequenceCompleted()) {
+ long lastRegularFrameNumber =
+ requestLastFrameNumbers.getLastRegularFrameNumber();
+ long lastReprocessFrameNumber =
+ requestLastFrameNumbers.getLastReprocessFrameNumber();
+ long lastZslStillFrameNumber =
+ requestLastFrameNumbers.getLastZslStillFrameNumber();
+ if (lastRegularFrameNumber <= completedFrameNumber
+ && lastReprocessFrameNumber <= completedReprocessFrameNumber
+ && lastZslStillFrameNumber <= completedZslStillFrameNumber) {
+ Log.v(TAG, String.format(
+ "Mark requestId %d as completed, because lastRegularFrame %d "
+ + "is <= %d, lastReprocessFrame %d is <= %d, "
+ + "lastZslStillFrame %d is <= %d", requestId,
+ lastRegularFrameNumber, completedFrameNumber,
+ lastReprocessFrameNumber, completedReprocessFrameNumber,
+ lastZslStillFrameNumber, completedZslStillFrameNumber));
+ requestLastFrameNumbers.markSequenceCompleted();
}
+ // Call onCaptureSequenceCompleted
int index = mCaptureCallbackMap.indexOfKey(requestId);
holder = (index >= 0) ?
mCaptureCallbackMap.valueAt(index) : null;
- if (holder != null) {
- long lastRegularFrameNumber =
- requestLastFrameNumbers.getLastRegularFrameNumber();
- long lastReprocessFrameNumber =
- requestLastFrameNumbers.getLastReprocessFrameNumber();
- long lastZslStillFrameNumber =
- requestLastFrameNumbers.getLastZslStillFrameNumber();
- // check if it's okay to remove request from mCaptureCallbackMap
- if (lastRegularFrameNumber <= completedFrameNumber
- && lastReprocessFrameNumber <= completedReprocessFrameNumber
- && lastZslStillFrameNumber <= completedZslStillFrameNumber) {
- sequenceCompleted = true;
- mCaptureCallbackMap.removeAt(index);
- if (DEBUG) {
- Log.v(TAG, String.format(
- "Remove holder for requestId %d, because lastRegularFrame %d "
- + "is <= %d, lastReprocessFrame %d is <= %d, "
- + "lastZslStillFrame %d is <= %d", requestId,
- lastRegularFrameNumber, completedFrameNumber,
- lastReprocessFrameNumber, completedReprocessFrameNumber,
- lastZslStillFrameNumber, completedZslStillFrameNumber));
+ if (holder != null && requestLastFrameNumbers.isSequenceCompleted()) {
+ Runnable resultDispatch = new Runnable() {
+ @Override
+ public void run() {
+ if (!CameraDeviceImpl.this.isClosed()){
+ if (DEBUG) {
+ Log.d(TAG, String.format(
+ "fire sequence complete for request %d",
+ requestId));
+ }
+
+ holder.getCallback().onCaptureSequenceCompleted(
+ CameraDeviceImpl.this,
+ requestId,
+ requestLastFrameNumbers.getLastFrameNumber());
+ }
}
+ };
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ holder.getExecutor().execute(resultDispatch);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
}
- // If no callback is registered for this requestId or sequence completed, remove it
- // from the frame number->request pair because it's not needed anymore.
- if (holder == null || sequenceCompleted) {
+ if (requestLastFrameNumbers.isSequenceCompleted() &&
+ requestLastFrameNumbers.isInflightCompleted()) {
+ int index = mCaptureCallbackMap.indexOfKey(requestId);
+ if (index >= 0) {
+ mCaptureCallbackMap.removeAt(index);
+ }
+ if (DEBUG) {
+ Log.v(TAG, String.format(
+ "Remove holder for requestId %d", requestId));
+ }
iter.remove();
}
+ }
+ }
- // Call onCaptureSequenceCompleted
- if (sequenceCompleted) {
- Runnable resultDispatch = new Runnable() {
- @Override
- public void run() {
- if (!CameraDeviceImpl.this.isClosed()){
- if (DEBUG) {
- Log.d(TAG, String.format(
- "fire sequence complete for request %d",
- requestId));
- }
+ private void removeCompletedCallbackHolderLocked(long lastCompletedRegularFrameNumber,
+ long lastCompletedReprocessFrameNumber, long lastCompletedZslStillFrameNumber) {
+ if (DEBUG) {
+ Log.v(TAG, String.format("remove completed callback holders for "
+ + "lastCompletedRegularFrameNumber %d, "
+ + "lastCompletedReprocessFrameNumber %d, "
+ + "lastCompletedZslStillFrameNumber %d",
+ lastCompletedRegularFrameNumber,
+ lastCompletedReprocessFrameNumber,
+ lastCompletedZslStillFrameNumber));
+ }
- holder.getCallback().onCaptureSequenceCompleted(
- CameraDeviceImpl.this,
- requestId,
- requestLastFrameNumbers.getLastFrameNumber());
- }
+ Iterator<RequestLastFrameNumbersHolder> iter = mRequestLastFrameNumbersList.iterator();
+ while (iter.hasNext()) {
+ final RequestLastFrameNumbersHolder requestLastFrameNumbers = iter.next();
+ final int requestId = requestLastFrameNumbers.getRequestId();
+ final CaptureCallbackHolder holder;
+ if (mRemoteDevice == null) {
+ Log.w(TAG, "Camera closed while removing completed callback holders");
+ return;
+ }
+
+ long lastRegularFrameNumber =
+ requestLastFrameNumbers.getLastRegularFrameNumber();
+ long lastReprocessFrameNumber =
+ requestLastFrameNumbers.getLastReprocessFrameNumber();
+ long lastZslStillFrameNumber =
+ requestLastFrameNumbers.getLastZslStillFrameNumber();
+
+ if (lastRegularFrameNumber <= lastCompletedRegularFrameNumber
+ && lastReprocessFrameNumber <= lastCompletedReprocessFrameNumber
+ && lastZslStillFrameNumber <= lastCompletedZslStillFrameNumber) {
+
+ if (requestLastFrameNumbers.isSequenceCompleted()) {
+ int index = mCaptureCallbackMap.indexOfKey(requestId);
+ if (index >= 0) {
+ mCaptureCallbackMap.removeAt(index);
}
- };
- final long ident = Binder.clearCallingIdentity();
- try {
- holder.getExecutor().execute(resultDispatch);
- } finally {
- Binder.restoreCallingIdentity(ident);
+ if (DEBUG) {
+ Log.v(TAG, String.format(
+ "Remove holder for requestId %d, because lastRegularFrame %d "
+ + "is <= %d, lastReprocessFrame %d is <= %d, "
+ + "lastZslStillFrame %d is <= %d", requestId,
+ lastRegularFrameNumber, lastCompletedRegularFrameNumber,
+ lastReprocessFrameNumber, lastCompletedReprocessFrameNumber,
+ lastZslStillFrameNumber, lastCompletedZslStillFrameNumber));
+ }
+ iter.remove();
+ } else {
+ if (DEBUG) {
+ Log.v(TAG, "Sequence not yet completed for request id " + requestId);
+ }
+ requestLastFrameNumbers.markInflightCompleted();
}
}
}
@@ -1702,6 +1759,12 @@
return;
}
+ // Remove all capture callbacks now that device has gone to IDLE state.
+ removeCompletedCallbackHolderLocked(
+ Long.MAX_VALUE, /*lastCompletedRegularFrameNumber*/
+ Long.MAX_VALUE, /*lastCompletedReprocessFrameNumber*/
+ Long.MAX_VALUE /*lastCompletedZslStillFrameNumber*/);
+
if (!CameraDeviceImpl.this.mIdle) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -1747,7 +1810,7 @@
return;
}
- checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber,
+ checkEarlyTriggerSequenceCompleteLocked(mRepeatingRequestId, lastFrameNumber,
mRepeatingRequestTypes);
// Check if there is already a new repeating request
if (mRepeatingRequestId == repeatingRequestId) {
@@ -1766,9 +1829,18 @@
public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
int requestId = resultExtras.getRequestId();
final long frameNumber = resultExtras.getFrameNumber();
+ final long lastCompletedRegularFrameNumber =
+ resultExtras.getLastCompletedRegularFrameNumber();
+ final long lastCompletedReprocessFrameNumber =
+ resultExtras.getLastCompletedReprocessFrameNumber();
+ final long lastCompletedZslFrameNumber =
+ resultExtras.getLastCompletedZslFrameNumber();
if (DEBUG) {
- Log.d(TAG, "Capture started for id " + requestId + " frame number " + frameNumber);
+ Log.d(TAG, "Capture started for id " + requestId + " frame number " + frameNumber
+ + ": completedRegularFrameNumber " + lastCompletedRegularFrameNumber
+ + ", completedReprocessFrameNUmber " + lastCompletedReprocessFrameNumber
+ + ", completedZslFrameNumber " + lastCompletedZslFrameNumber);
}
final CaptureCallbackHolder holder;
@@ -1784,6 +1856,12 @@
return;
}
+ // Check if it's okay to remove completed callbacks from mCaptureCallbackMap.
+ // A callback is completed if the corresponding inflight request has been removed
+ // from the inflight queue in cameraservice.
+ removeCompletedCallbackHolderLocked(lastCompletedRegularFrameNumber,
+ lastCompletedReprocessFrameNumber, lastCompletedZslFrameNumber);
+
// Get the callback for this frame ID, if there is one
holder = CameraDeviceImpl.this.mCaptureCallbackMap.get(requestId);
diff --git a/core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java
index 1d9d644..413caf5 100644
--- a/core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraOfflineSessionImpl.java
@@ -182,6 +182,12 @@
return;
}
+ // Remove all capture callbacks now that device has gone to IDLE state.
+ removeCompletedCallbackHolderLocked(
+ Long.MAX_VALUE, /*lastCompletedRegularFrameNumber*/
+ Long.MAX_VALUE, /*lastCompletedReprocessFrameNumber*/
+ Long.MAX_VALUE /*lastCompletedZslStillFrameNumber*/);
+
Runnable idleDispatch = new Runnable() {
@Override
public void run() {
@@ -204,10 +210,22 @@
public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
int requestId = resultExtras.getRequestId();
final long frameNumber = resultExtras.getFrameNumber();
+ final long lastCompletedRegularFrameNumber =
+ resultExtras.getLastCompletedRegularFrameNumber();
+ final long lastCompletedReprocessFrameNumber =
+ resultExtras.getLastCompletedReprocessFrameNumber();
+ final long lastCompletedZslFrameNumber =
+ resultExtras.getLastCompletedZslFrameNumber();
final CaptureCallbackHolder holder;
synchronized(mInterfaceLock) {
+ // Check if it's okay to remove completed callbacks from mCaptureCallbackMap.
+ // A callback is completed if the corresponding inflight request has been removed
+ // from the inflight queue in cameraservice.
+ removeCompletedCallbackHolderLocked(lastCompletedRegularFrameNumber,
+ lastCompletedReprocessFrameNumber, lastCompletedZslFrameNumber);
+
// Get the callback for this frame ID, if there is one
holder = CameraOfflineSessionImpl.this.mCaptureCallbackMap.get(requestId);
@@ -601,6 +619,61 @@
}
}
+ private void removeCompletedCallbackHolderLocked(long lastCompletedRegularFrameNumber,
+ long lastCompletedReprocessFrameNumber, long lastCompletedZslStillFrameNumber) {
+ if (DEBUG) {
+ Log.v(TAG, String.format("remove completed callback holders for "
+ + "lastCompletedRegularFrameNumber %d, "
+ + "lastCompletedReprocessFrameNumber %d, "
+ + "lastCompletedZslStillFrameNumber %d",
+ lastCompletedRegularFrameNumber,
+ lastCompletedReprocessFrameNumber,
+ lastCompletedZslStillFrameNumber));
+ }
+
+ boolean isReprocess = false;
+ Iterator<RequestLastFrameNumbersHolder> iter =
+ mOfflineRequestLastFrameNumbersList.iterator();
+ while (iter.hasNext()) {
+ final RequestLastFrameNumbersHolder requestLastFrameNumbers = iter.next();
+ final int requestId = requestLastFrameNumbers.getRequestId();
+ final CaptureCallbackHolder holder;
+
+ int index = mCaptureCallbackMap.indexOfKey(requestId);
+ holder = (index >= 0) ?
+ mCaptureCallbackMap.valueAt(index) : null;
+ if (holder != null) {
+ long lastRegularFrameNumber =
+ requestLastFrameNumbers.getLastRegularFrameNumber();
+ long lastReprocessFrameNumber =
+ requestLastFrameNumbers.getLastReprocessFrameNumber();
+ long lastZslStillFrameNumber =
+ requestLastFrameNumbers.getLastZslStillFrameNumber();
+ if (lastRegularFrameNumber <= lastCompletedRegularFrameNumber
+ && lastReprocessFrameNumber <= lastCompletedReprocessFrameNumber
+ && lastZslStillFrameNumber <= lastCompletedZslStillFrameNumber) {
+ if (requestLastFrameNumbers.isSequenceCompleted()) {
+ mCaptureCallbackMap.removeAt(index);
+ if (DEBUG) {
+ Log.v(TAG, String.format(
+ "Remove holder for requestId %d, because lastRegularFrame %d "
+ + "is <= %d, lastReprocessFrame %d is <= %d, "
+ + "lastZslStillFrame %d is <= %d", requestId,
+ lastRegularFrameNumber, lastCompletedRegularFrameNumber,
+ lastReprocessFrameNumber, lastCompletedReprocessFrameNumber,
+ lastZslStillFrameNumber, lastCompletedZslStillFrameNumber));
+ }
+
+ iter.remove();
+ } else {
+ Log.e(TAG, "Sequence not yet completed for request id " + requestId);
+ continue;
+ }
+ }
+ }
+ }
+ }
+
public void notifyFailedSwitch() {
synchronized(mInterfaceLock) {
Runnable switchFailDispatch = new Runnable() {
diff --git a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
index 1ff5bd5..5d9da73 100644
--- a/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
+++ b/core/java/android/hardware/camera2/impl/CaptureResultExtras.java
@@ -30,6 +30,9 @@
private int partialResultCount;
private int errorStreamId;
private String errorPhysicalCameraId;
+ private long lastCompletedRegularFrameNumber;
+ private long lastCompletedReprocessFrameNumber;
+ private long lastCompletedZslFrameNumber;
public static final @android.annotation.NonNull Parcelable.Creator<CaptureResultExtras> CREATOR =
new Parcelable.Creator<CaptureResultExtras>() {
@@ -51,7 +54,9 @@
public CaptureResultExtras(int requestId, int subsequenceId, int afTriggerId,
int precaptureTriggerId, long frameNumber,
int partialResultCount, int errorStreamId,
- String errorPhysicalCameraId) {
+ String errorPhysicalCameraId, long lastCompletedRegularFrameNumber,
+ long lastCompletedReprocessFrameNumber,
+ long lastCompletedZslFrameNumber) {
this.requestId = requestId;
this.subsequenceId = subsequenceId;
this.afTriggerId = afTriggerId;
@@ -60,6 +65,9 @@
this.partialResultCount = partialResultCount;
this.errorStreamId = errorStreamId;
this.errorPhysicalCameraId = errorPhysicalCameraId;
+ this.lastCompletedRegularFrameNumber = lastCompletedRegularFrameNumber;
+ this.lastCompletedReprocessFrameNumber = lastCompletedReprocessFrameNumber;
+ this.lastCompletedZslFrameNumber = lastCompletedZslFrameNumber;
}
@Override
@@ -82,6 +90,9 @@
} else {
dest.writeBoolean(false);
}
+ dest.writeLong(lastCompletedRegularFrameNumber);
+ dest.writeLong(lastCompletedReprocessFrameNumber);
+ dest.writeLong(lastCompletedZslFrameNumber);
}
public void readFromParcel(Parcel in) {
@@ -96,6 +107,9 @@
if (errorPhysicalCameraIdPresent) {
errorPhysicalCameraId = in.readString();
}
+ lastCompletedRegularFrameNumber = in.readLong();
+ lastCompletedReprocessFrameNumber = in.readLong();
+ lastCompletedZslFrameNumber = in.readLong();
}
public String getErrorPhysicalCameraId() {
@@ -129,4 +143,16 @@
public int getErrorStreamId() {
return errorStreamId;
}
+
+ public long getLastCompletedRegularFrameNumber() {
+ return lastCompletedRegularFrameNumber;
+ }
+
+ public long getLastCompletedReprocessFrameNumber() {
+ return lastCompletedReprocessFrameNumber;
+ }
+
+ public long getLastCompletedZslFrameNumber() {
+ return lastCompletedZslFrameNumber;
+ }
}
diff --git a/core/java/android/hardware/camera2/impl/RequestLastFrameNumbersHolder.java b/core/java/android/hardware/camera2/impl/RequestLastFrameNumbersHolder.java
index bd1df9e..0ee4ebc 100644
--- a/core/java/android/hardware/camera2/impl/RequestLastFrameNumbersHolder.java
+++ b/core/java/android/hardware/camera2/impl/RequestLastFrameNumbersHolder.java
@@ -38,6 +38,10 @@
// The last ZSL still capture frame number for this request ID. It's
// CaptureCallback.NO_FRAMES_CAPTURED if the request ID has no zsl request.
private final long mLastZslStillFrameNumber;
+ // Whether the sequence is completed. (only consider capture result)
+ private boolean mSequenceCompleted;
+ // Whether the inflight request is completed. (consider result, buffers, and notifies)
+ private boolean mInflightCompleted;
/**
* Create a request-last-frame-numbers holder with a list of requests, request ID, and
@@ -89,6 +93,8 @@
mLastReprocessFrameNumber = lastReprocessFrameNumber;
mLastZslStillFrameNumber = lastZslStillFrameNumber;
mRequestId = requestInfo.getRequestId();
+ mSequenceCompleted = false;
+ mInflightCompleted = false;
}
/**
@@ -137,6 +143,8 @@
mLastZslStillFrameNumber = lastZslStillFrameNumber;
mLastReprocessFrameNumber = CameraCaptureSession.CaptureCallback.NO_FRAMES_CAPTURED;
mRequestId = requestId;
+ mSequenceCompleted = false;
+ mInflightCompleted = false;
}
/**
@@ -177,5 +185,34 @@
public int getRequestId() {
return mRequestId;
}
+
+ /**
+ * Return whether the capture sequence is completed.
+ */
+ public boolean isSequenceCompleted() {
+ return mSequenceCompleted;
+ }
+
+ /**
+ * Mark the capture sequence as completed.
+ */
+ public void markSequenceCompleted() {
+ mSequenceCompleted = true;
+ }
+
+ /**
+ * Return whether the inflight capture is completed.
+ */
+ public boolean isInflightCompleted() {
+ return mInflightCompleted;
+ }
+
+ /**
+ * Mark the inflight capture as completed.
+ */
+ public void markInflightCompleted() {
+ mInflightCompleted = true;
+ }
+
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index fbc9ac32..fdd578c 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -109,11 +109,12 @@
}
if (holder == null) {
return new CaptureResultExtras(ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE,
- ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, null);
+ ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE, null,
+ ILLEGAL_VALUE, ILLEGAL_VALUE, ILLEGAL_VALUE);
}
return new CaptureResultExtras(holder.getRequestId(), holder.getSubsequeceId(),
/*afTriggerId*/0, /*precaptureTriggerId*/0, holder.getFrameNumber(),
- /*partialResultCount*/1, errorStreamId, null);
+ /*partialResultCount*/1, errorStreamId, null, holder.getFrameNumber(), -1, -1);
}
/**
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index a6bd74a..473e6c5 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -468,8 +468,8 @@
}
/**
- * Returns true iff. the capabilities requested in this NetworkRequest are satisfied by the
- * provided {@link NetworkCapabilities}.
+ * Returns true if and only if the capabilities requested in this NetworkRequest are satisfied
+ * by the provided {@link NetworkCapabilities}.
*
* @param nc Capabilities that should satisfy this NetworkRequest. null capabilities do not
* satisfy any request.
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index a4c99c0..39038f5 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -1318,15 +1318,15 @@
Process.ProcessStartResult result;
try {
- // As app zygote is for generating isolated process, at the end it can't access
- // apps data, so doesn't need to its data info.
+ // We will bind mount app data dirs so app zygote can't access /data/data, while
+ // we don't need to bind mount storage dirs as /storage won't be mounted.
result = startViaZygote(processClass, niceName, uid, gid,
gids, runtimeFlags, 0 /* mountExternal */, 0 /* targetSdkVersion */, seInfo,
abi, instructionSet, null /* appDataDir */, null /* invokeWith */,
true /* startChildZygote */, null /* packageName */,
ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS /* zygotePolicyFlags */, false /* isTopApp */,
null /* disabledCompatChanges */, null /* pkgDataInfoMap */,
- null /* whitelistedDataInfoMap */, false /* bindMountAppsData*/,
+ null /* whitelistedDataInfoMap */, true /* bindMountAppsData*/,
/* bindMountAppStorageDirs */ false, extraArgs);
} catch (ZygoteStartFailedEx ex) {
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 1f6555c..0827fef 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -78,6 +78,7 @@
private static final int DEFAULT_SOURCE = SOURCE_CONTACT;
private static final int DEFAULT_CALLS_SOURCE = SOURCE_STAR;
+ public static final String MANUAL_RULE_ID = "MANUAL_RULE";
public static final String EVENTS_DEFAULT_RULE_ID = "EVENTS_DEFAULT_RULE";
public static final String EVERY_NIGHT_DEFAULT_RULE_ID = "EVERY_NIGHT_DEFAULT_RULE";
public static final List<String> DEFAULT_RULE_IDS = Arrays.asList(EVERY_NIGHT_DEFAULT_RULE_ID,
@@ -959,6 +960,48 @@
};
/**
+ * Converts a ZenModeConfig to a ZenPolicy
+ */
+ public ZenPolicy toZenPolicy() {
+ ZenPolicy.Builder builder = new ZenPolicy.Builder()
+ .allowCalls(allowCalls
+ ? ZenModeConfig.getZenPolicySenders(allowCallsFrom)
+ : ZenPolicy.PEOPLE_TYPE_NONE)
+ .allowRepeatCallers(allowRepeatCallers)
+ .allowMessages(allowMessages
+ ? ZenModeConfig.getZenPolicySenders(allowMessagesFrom)
+ : ZenPolicy.PEOPLE_TYPE_NONE)
+ .allowReminders(allowReminders)
+ .allowEvents(allowEvents)
+ .allowAlarms(allowAlarms)
+ .allowMedia(allowMedia)
+ .allowSystem(allowSystem)
+ .allowConversations(allowConversations
+ ? ZenModeConfig.getZenPolicySenders(allowConversationsFrom)
+ : ZenPolicy.PEOPLE_TYPE_NONE);
+ if (suppressedVisualEffects == 0) {
+ builder.showAllVisualEffects();
+ } else {
+ // configs don't have an unset state: wither true or false.
+ builder.showFullScreenIntent(
+ (suppressedVisualEffects & Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT) == 0);
+ builder.showLights(
+ (suppressedVisualEffects & SUPPRESSED_EFFECT_LIGHTS) == 0);
+ builder.showPeeking(
+ (suppressedVisualEffects & SUPPRESSED_EFFECT_PEEK) == 0);
+ builder.showStatusBarIcons(
+ (suppressedVisualEffects & Policy.SUPPRESSED_EFFECT_STATUS_BAR) == 0);
+ builder.showBadges(
+ (suppressedVisualEffects & Policy.SUPPRESSED_EFFECT_BADGE) == 0);
+ builder.showInAmbientDisplay(
+ (suppressedVisualEffects & Policy.SUPPRESSED_EFFECT_AMBIENT) == 0);
+ builder.showInNotificationList(
+ (suppressedVisualEffects & Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST) == 0);
+ }
+ return builder.build();
+ }
+
+ /**
* Converts a zenPolicy to a notificationPolicy using this ZenModeConfig's values as its
* defaults for all unset values in zenPolicy
*/
diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java
index 87295e1..6d0bcff 100644
--- a/core/java/android/service/notification/ZenPolicy.java
+++ b/core/java/android/service/notification/ZenPolicy.java
@@ -24,6 +24,7 @@
import android.os.Parcelable;
import android.util.proto.ProtoOutputStream;
+import java.io.ByteArrayOutputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
@@ -1111,6 +1112,40 @@
}
/**
+ * Converts a policy to a statsd proto.
+ * @hides
+ */
+ public byte[] toProto() {
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ ProtoOutputStream proto = new ProtoOutputStream(bytes);
+
+ proto.write(DNDPolicyProto.CALLS, getPriorityCategoryCalls());
+ proto.write(DNDPolicyProto.REPEAT_CALLERS, getPriorityCategoryRepeatCallers());
+ proto.write(DNDPolicyProto.MESSAGES, getPriorityCategoryMessages());
+ proto.write(DNDPolicyProto.CONVERSATIONS, getPriorityCategoryConversations());
+ proto.write(DNDPolicyProto.REMINDERS, getPriorityCategoryReminders());
+ proto.write(DNDPolicyProto.EVENTS, getPriorityCategoryEvents());
+ proto.write(DNDPolicyProto.ALARMS, getPriorityCategoryAlarms());
+ proto.write(DNDPolicyProto.MEDIA, getPriorityCategoryMedia());
+ proto.write(DNDPolicyProto.SYSTEM, getPriorityCategorySystem());
+
+ proto.write(DNDPolicyProto.FULLSCREEN, getVisualEffectFullScreenIntent());
+ proto.write(DNDPolicyProto.LIGHTS, getVisualEffectLights());
+ proto.write(DNDPolicyProto.PEEK, getVisualEffectPeek());
+ proto.write(DNDPolicyProto.STATUS_BAR, getVisualEffectStatusBar());
+ proto.write(DNDPolicyProto.BADGE, getVisualEffectBadge());
+ proto.write(DNDPolicyProto.AMBIENT, getVisualEffectAmbient());
+ proto.write(DNDPolicyProto.NOTIFICATION_LIST, getVisualEffectNotificationList());
+
+ proto.write(DNDPolicyProto.ALLOW_CALLS_FROM, getPriorityCallSenders());
+ proto.write(DNDPolicyProto.ALLOW_MESSAGES_FROM, getPriorityMessageSenders());
+ proto.write(DNDPolicyProto.ALLOW_CONVERSATIONS_FROM, getPriorityConversationSenders());
+
+ proto.flush();
+ return bytes.toByteArray();
+ }
+
+ /**
* Makes deep copy of this ZenPolicy.
* @hide
*/
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 9b293eb..ef21900 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -157,8 +157,8 @@
* Listen for changes to the device's cell location. Note that
* this will result in frequent callbacks to the listener.
* {@more}
- * Requires Permission: {@link android.Manifest.permission#ACCESS_COARSE_LOCATION
- * ACCESS_COARSE_LOCATION}
+ * Requires Permission: {@link android.Manifest.permission#ACCESS_FINE_LOCATION
+ * ACCESS_FINE_LOCATION}
* <p>
* If you need regular location updates but want more control over
* the update interval or location precision, you can set up a listener
diff --git a/core/java/android/view/ImeFocusController.java b/core/java/android/view/ImeFocusController.java
index a480072..825077ff 100644
--- a/core/java/android/view/ImeFocusController.java
+++ b/core/java/android/view/ImeFocusController.java
@@ -125,6 +125,13 @@
final View viewForWindowFocus = focusedView != null ? focusedView : mViewRootImpl.mView;
onViewFocusChanged(viewForWindowFocus, true);
+ // Skip starting input when the next focused view is same as served view and the served
+ // input connection still exists.
+ final boolean nextFocusIsServedView = mServedView != null && mServedView == focusedView;
+ if (nextFocusIsServedView && immDelegate.isAcceptingText()) {
+ forceFocus = false;
+ }
+
immDelegate.startInputAsyncOnWindowFocusGain(viewForWindowFocus,
windowAttribute.softInputMode, windowAttribute.flags, forceFocus);
}
@@ -247,6 +254,7 @@
void setCurrentRootView(ViewRootImpl rootView);
boolean isCurrentRootView(ViewRootImpl rootView);
boolean isRestartOnNextWindowFocus(boolean reset);
+ boolean isAcceptingText();
}
public View getServedView() {
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index ef9edc6c..e4d53c6 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -791,7 +791,7 @@
WindowInsetsAnimationControlListener listener,
boolean fromIme, long durationMs, @Nullable Interpolator interpolator,
@AnimationType int animationType) {
- if (!checkDisplayFramesForControlling()) {
+ if ((mState.calculateUncontrollableInsetsFromFrame(mFrame) & types) != 0) {
listener.onCancelled(null);
return;
}
@@ -801,13 +801,6 @@
false /* useInsetsAnimationThread */);
}
- private boolean checkDisplayFramesForControlling() {
-
- // If the frame of our window doesn't span the entire display, the control API makes very
- // little sense, as we don't deal with negative insets. So just cancel immediately.
- return mState.getDisplayFrame().equals(mFrame);
- }
-
private void controlAnimationUnchecked(@InsetsType int types,
@Nullable CancellationSignal cancellationSignal,
WindowInsetsAnimationControlListener listener, Rect frame, boolean fromIme,
@@ -1285,9 +1278,6 @@
}
private @InsetsType int calculateControllableTypes() {
- if (!checkDisplayFramesForControlling()) {
- return 0;
- }
@InsetsType int result = 0;
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
@@ -1295,7 +1285,7 @@
result |= toPublicType(consumer.mType);
}
}
- return result;
+ return result & ~mState.calculateUncontrollableInsetsFromFrame(mFrame);
}
/**
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index 3869484..ae70a49 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -22,6 +22,8 @@
import static android.view.InsetsController.DEBUG;
import static android.view.InsetsState.toPublicType;
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
+
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.graphics.Rect;
@@ -271,10 +273,13 @@
// no-op for types that always return ShowResult#SHOW_IMMEDIATELY.
}
- void updateSource(InsetsSource newSource) {
+ @VisibleForTesting(visibility = PACKAGE)
+ public void updateSource(InsetsSource newSource) {
InsetsSource source = mState.peekSource(mType);
if (source == null || mController.getAnimationType(mType) == ANIMATION_TYPE_NONE
|| source.getFrame().equals(newSource.getFrame())) {
+ mPendingFrame = null;
+ mPendingVisibleFrame = null;
mState.addSource(newSource);
return;
}
@@ -292,7 +297,8 @@
if (DEBUG) Log.d(TAG, "updateSource: " + newSource);
}
- boolean notifyAnimationFinished() {
+ @VisibleForTesting(visibility = PACKAGE)
+ public boolean notifyAnimationFinished() {
if (mPendingFrame != null) {
InsetsSource source = mState.getSource(mType);
source.setFrame(mPendingFrame);
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 3822ee5..f0bca26 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -245,6 +245,44 @@
return insets.toRect();
}
+ /**
+ * Calculate which insets *cannot* be controlled, because the frame does not cover the
+ * respective side of the inset.
+ *
+ * If the frame of our window doesn't cover the entire inset, the control API makes very
+ * little sense, as we don't deal with negative insets.
+ */
+ @InsetsType
+ public int calculateUncontrollableInsetsFromFrame(Rect frame) {
+ int blocked = 0;
+ for (int type = FIRST_TYPE; type <= LAST_TYPE; type++) {
+ InsetsSource source = mSources.get(type);
+ if (source == null) {
+ continue;
+ }
+ if (!canControlSide(frame, getInsetSide(
+ source.calculateInsets(frame, true /* ignoreVisibility */)))) {
+ blocked |= toPublicType(type);
+ }
+ }
+ return blocked;
+ }
+
+ private boolean canControlSide(Rect frame, int side) {
+ switch (side) {
+ case ISIDE_LEFT:
+ case ISIDE_RIGHT:
+ return frame.left == mDisplayFrame.left && frame.right == mDisplayFrame.right;
+ case ISIDE_TOP:
+ case ISIDE_BOTTOM:
+ return frame.top == mDisplayFrame.top && frame.bottom == mDisplayFrame.bottom;
+ case ISIDE_FLOATING:
+ return true;
+ default:
+ return false;
+ }
+ }
+
private void processSource(InsetsSource source, Rect relativeFrame, boolean ignoreVisibility,
Insets[] typeInsetsMap, @Nullable @InternalInsetsSide SparseIntArray typeSideMap,
@Nullable boolean[] typeVisibilityMap) {
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index eaaaa80..214da38 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -635,7 +635,7 @@
"android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH";
/**
- * Key used to request extra data for accessibility scanning tool's purposes.
+ * Key used to request extra data for the rendering information.
* The key requests that a {@link AccessibilityNodeInfo.ExtraRenderingInfo} be added to this
* info. This request is made with {@link #refreshWithExtraData(String, Bundle)} without
* argument.
@@ -5847,12 +5847,15 @@
}
/**
- * Gets the size object containing the height and the width of layout params if the node is
- * a {@link ViewGroup} or a {@link TextView}, or null otherwise. Useful for accessibility
- * scanning tool to understand whether the text is scalable and fits the view or not.
+ * Gets the size object containing the height and the width of
+ * {@link android.view.ViewGroup.LayoutParams} if the node is a {@link ViewGroup} or
+ * a {@link TextView}, or null otherwise. Useful for some accessibility services to
+ * understand whether the text is scalable and fits the view or not.
*
- * @return a {@link Size} stores layout height and layout width of the view,
- * or null otherwise.
+ * @return a {@link Size} stores layout height and layout width of the view, or null
+ * otherwise. And the size value may be in pixels,
+ * {@link android.view.ViewGroup.LayoutParams#MATCH_PARENT},
+ * or {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}
*/
public @Nullable Size getLayoutSize() {
return mLayoutSize;
@@ -5870,9 +5873,9 @@
}
/**
- * Gets the text size if the node is a {@link TextView}, or -1 otherwise. Useful for
- * accessibility scanning tool to understand whether the text is scalable and fits the view
- * or not.
+ * Gets the text size if the node is a {@link TextView}, or -1 otherwise. Useful for some
+ * accessibility services to understand whether the text is scalable and fits the view or
+ * not.
*
* @return the text size of a {@code TextView}, or -1 otherwise.
*/
@@ -5893,7 +5896,7 @@
/**
* Gets the text size unit if the node is a {@link TextView}, or -1 otherwise.
* Text size returned from {@link #getTextSizeInPx} in raw pixels may scale by factors and
- * convert from other units. Useful for accessibility scanning tool to understand whether
+ * convert from other units. Useful for some accessibility services to understand whether
* the text is scalable and fits the view or not.
*
* @return the text size unit which type is {@link TypedValue#TYPE_DIMENSION} of a
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 3112039..fbfeda6 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -751,6 +751,8 @@
}
} catch (RemoteException e) {
Log.e(TAG, "Could not figure out if there was an autofill session", e);
+ } catch (SyncResultReceiver.TimeoutException e) {
+ Log.e(TAG, "Fail to get session restore status: " + e);
}
}
}
@@ -864,7 +866,9 @@
mService.getFillEventHistory(receiver);
return receiver.getParcelableResult();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw e.rethrowFromSystemServer();
+ } catch (SyncResultReceiver.TimeoutException e) {
+ Log.e(TAG, "Fail to get fill event history: " + e);
return null;
}
}
@@ -1477,10 +1481,13 @@
final SyncResultReceiver receiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
try {
- mService.isServiceEnabled(mContext.getUserId(), mContext.getPackageName(), receiver);
+ mService.isServiceEnabled(mContext.getUserId(), mContext.getPackageName(),
+ receiver);
return receiver.getIntResult() == 1;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } catch (SyncResultReceiver.TimeoutException e) {
+ throw new RuntimeException("Fail to get enabled autofill services status.");
}
}
@@ -1498,6 +1505,8 @@
return receiver.getParcelableResult();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } catch (SyncResultReceiver.TimeoutException e) {
+ throw new RuntimeException("Fail to get autofill services component name.");
}
}
@@ -1522,8 +1531,9 @@
mService.getUserDataId(receiver);
return receiver.getStringResult();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
- return null;
+ throw e.rethrowFromSystemServer();
+ } catch (SyncResultReceiver.TimeoutException e) {
+ throw new RuntimeException("Fail to get user data id for field classification.");
}
}
@@ -1544,8 +1554,9 @@
mService.getUserData(receiver);
return receiver.getParcelableResult();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
- return null;
+ throw e.rethrowFromSystemServer();
+ } catch (SyncResultReceiver.TimeoutException e) {
+ throw new RuntimeException("Fail to get user data for field classification.");
}
}
@@ -1561,7 +1572,7 @@
try {
mService.setUserData(userData);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw e.rethrowFromSystemServer();
}
}
@@ -1583,8 +1594,9 @@
mService.isFieldClassificationEnabled(receiver);
return receiver.getIntResult() == 1;
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
- return false;
+ throw e.rethrowFromSystemServer();
+ } catch (SyncResultReceiver.TimeoutException e) {
+ throw new RuntimeException("Fail to get field classification enabled status.");
}
}
@@ -1606,8 +1618,9 @@
mService.getDefaultFieldClassificationAlgorithm(receiver);
return receiver.getStringResult();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
- return null;
+ throw e.rethrowFromSystemServer();
+ } catch (SyncResultReceiver.TimeoutException e) {
+ throw new RuntimeException("Fail to get default field classification algorithm.");
}
}
@@ -1627,8 +1640,9 @@
final String[] algorithms = receiver.getStringArrayResult();
return algorithms != null ? Arrays.asList(algorithms) : Collections.emptyList();
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
- return null;
+ throw e.rethrowFromSystemServer();
+ } catch (SyncResultReceiver.TimeoutException e) {
+ throw new RuntimeException("Fail to get available field classification algorithms.");
}
}
@@ -1651,6 +1665,8 @@
return receiver.getIntResult() == 1;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } catch (SyncResultReceiver.TimeoutException e) {
+ throw new RuntimeException("Fail to get autofill supported status.");
}
}
@@ -2040,13 +2056,16 @@
}
final SyncResultReceiver resultReceiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
- final int resultCode;
+ int resultCode;
try {
mService.setAugmentedAutofillWhitelist(toList(packages), toList(activities),
resultReceiver);
resultCode = resultReceiver.getIntResult();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } catch (SyncResultReceiver.TimeoutException e) {
+ Log.e(TAG, "Fail to get the result of set AugmentedAutofill whitelist. " + e);
+ return;
}
switch (resultCode) {
case RESULT_OK:
@@ -2283,7 +2302,7 @@
// In theory, we could ignore this error since it's not a big deal, but
// in reality, we rather crash the app anyways, as the failure could be
// a consequence of something going wrong on the server side...
- e.rethrowFromSystemServer();
+ throw e.rethrowFromSystemServer();
}
}
@@ -2661,7 +2680,7 @@
try {
mService.onPendingSaveUi(operation, token);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ Log.e(TAG, "Error in onPendingSaveUi: ", e);
}
}
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 756ff78..484b1c1 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -487,6 +487,8 @@
return resultReceiver.getParcelableResult();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } catch (SyncResultReceiver.TimeoutException e) {
+ throw new RuntimeException("Fail to get service componentName.");
}
}
@@ -516,6 +518,9 @@
return resultReceiver.getParcelableResult();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } catch (SyncResultReceiver.TimeoutException e) {
+ Log.e(TAG, "Fail to get service settings componentName: " + e);
+ return null;
}
}
@@ -567,9 +572,13 @@
final SyncResultReceiver resultReceiver = syncRun(
(r) -> mService.getContentCaptureConditions(mContext.getPackageName(), r));
- final ArrayList<ContentCaptureCondition> result = resultReceiver
- .getParcelableListResult();
- return toSet(result);
+ try {
+ final ArrayList<ContentCaptureCondition> result = resultReceiver
+ .getParcelableListResult();
+ return toSet(result);
+ } catch (SyncResultReceiver.TimeoutException e) {
+ throw new RuntimeException("Fail to get content capture conditions.");
+ }
}
/**
@@ -639,15 +648,21 @@
public boolean isContentCaptureFeatureEnabled() {
final SyncResultReceiver resultReceiver = syncRun(
(r) -> mService.isContentCaptureFeatureEnabled(r));
- final int resultCode = resultReceiver.getIntResult();
- switch (resultCode) {
- case RESULT_CODE_TRUE:
- return true;
- case RESULT_CODE_FALSE:
- return false;
- default:
- Log.wtf(TAG, "received invalid result: " + resultCode);
- return false;
+
+ try {
+ final int resultCode = resultReceiver.getIntResult();
+ switch (resultCode) {
+ case RESULT_CODE_TRUE:
+ return true;
+ case RESULT_CODE_FALSE:
+ return false;
+ default:
+ Log.wtf(TAG, "received invalid result: " + resultCode);
+ return false;
+ }
+ } catch (SyncResultReceiver.TimeoutException e) {
+ Log.e(TAG, "Fail to get content capture feature enable status: " + e);
+ return false;
}
}
@@ -663,7 +678,7 @@
try {
mService.removeData(request);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw e.rethrowFromSystemServer();
}
}
@@ -691,7 +706,7 @@
new DataShareAdapterDelegate(executor, dataShareWriteAdapter,
mDataShareAdapterResourceManager));
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw e.rethrowFromSystemServer();
}
}
@@ -709,10 +724,12 @@
if (resultCode == RESULT_CODE_SECURITY_EXCEPTION) {
throw new SecurityException(resultReceiver.getStringResult());
}
- return resultReceiver;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
+ } catch (SyncResultReceiver.TimeoutException e) {
+ throw new RuntimeException("Fail to get syn run result from SyncResultReceiver.");
}
+ return resultReceiver;
}
/** @hide */
diff --git a/core/java/android/view/inputmethod/InlineSuggestion.java b/core/java/android/view/inputmethod/InlineSuggestion.java
index e4ac588..b8893ce 100644
--- a/core/java/android/view/inputmethod/InlineSuggestion.java
+++ b/core/java/android/view/inputmethod/InlineSuggestion.java
@@ -317,8 +317,24 @@
*/
@MainThread
private void handleOnSurfacePackage(SurfaceControlViewHost.SurfacePackage surfacePackage) {
+ if (surfacePackage == null) {
+ return;
+ }
+ if (mSurfacePackage != null || mSurfacePackageConsumer == null) {
+ // The surface package is not consumed, release it immediately.
+ surfacePackage.release();
+ try {
+ mInlineContentProvider.onSurfacePackageReleased();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Error calling onSurfacePackageReleased(): " + e);
+ }
+ return;
+ }
mSurfacePackage = surfacePackage;
- if (mSurfacePackage != null && mSurfacePackageConsumer != null) {
+ if (mSurfacePackage == null) {
+ return;
+ }
+ if (mSurfacePackageConsumer != null) {
mSurfacePackageConsumer.accept(mSurfacePackage);
mSurfacePackageConsumer = null;
}
@@ -334,6 +350,10 @@
}
mSurfacePackage = null;
}
+ // Clear the pending surface package consumer, if any. This can happen if the IME
+ // attaches the view to window and then quickly detaches it from the window, before
+ // the surface package requested upon attaching to window was returned.
+ mSurfacePackageConsumer = null;
}
@MainThread
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 71dd665..477dd1d 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -616,12 +616,19 @@
// For some reason we didn't do a startInput + windowFocusGain, so
// we'll just do a window focus gain and call it a day.
try {
- if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
+ View servedView = controller.getServedView();
+ boolean nextFocusIsServedView = servedView != null && servedView == focusedView;
+ if (DEBUG) {
+ Log.v(TAG, "Reporting focus gain, without startInput"
+ + ", nextFocusIsServedView=" + nextFocusIsServedView);
+ }
mService.startInputOrWindowGainedFocus(
StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
focusedView.getWindowToken(), startInputFlags, softInputMode,
windowFlags,
- null, null, 0 /* missingMethodFlags */,
+ nextFocusIsServedView ? mCurrentTextBoxAttribute : null,
+ nextFocusIsServedView ? mServedInputConnectionWrapper : null,
+ 0 /* missingMethodFlags */,
mCurRootView.mContext.getApplicationInfo().targetSdkVersion);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -646,8 +653,7 @@
public void setCurrentRootView(ViewRootImpl rootView) {
synchronized (mH) {
if (mCurRootView != null) {
- // Reset the last served view and restart window focus state of the root view.
- mCurRootView.getImeFocusController().setServedView(null);
+ // Restart the input when the next window focus state of the root view changed.
mRestartOnNextWindowFocus = true;
}
mCurRootView = rootView;
@@ -677,6 +683,18 @@
}
return result;
}
+
+ /**
+ * For {@link ImeFocusController} to check if the currently served view is accepting full
+ * text edits.
+ */
+ @Override
+ public boolean isAcceptingText() {
+ synchronized (mH) {
+ return mServedInputConnectionWrapper != null
+ && mServedInputConnectionWrapper.getInputConnection() != null;
+ }
+ }
}
/** @hide */
diff --git a/core/java/android/widget/inline/InlineContentView.java b/core/java/android/widget/inline/InlineContentView.java
index 8657e82..6a85de5 100644
--- a/core/java/android/widget/inline/InlineContentView.java
+++ b/core/java/android/widget/inline/InlineContentView.java
@@ -197,7 +197,9 @@
mSurfacePackageUpdater.getSurfacePackage(
sp -> {
if (DEBUG) Log.v(TAG, "Received new SurfacePackage");
- mSurfaceView.setChildSurfacePackage(sp);
+ if (getViewRootImpl() != null) {
+ mSurfaceView.setChildSurfacePackage(sp);
+ }
});
}
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index b36c71f..2d4d957 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -1121,7 +1121,7 @@
final ComponentName cn = getNearbySharingComponent();
if (cn == null) return null;
- final Intent resolveIntent = new Intent();
+ final Intent resolveIntent = new Intent(originalIntent);
resolveIntent.setComponent(cn);
final ResolveInfo ri = getPackageManager().resolveActivity(
resolveIntent, PackageManager.GET_META_DATA);
@@ -1285,6 +1285,12 @@
ViewGroup parent) {
ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate(
R.layout.chooser_grid_preview_image, parent, false);
+
+ final ViewGroup actionRow =
+ (ViewGroup) contentPreviewLayout.findViewById(R.id.chooser_action_row);
+ //TODO: addActionButton(actionRow, createCopyButton());
+ addActionButton(actionRow, createNearbyButton(targetIntent));
+
mPreviewCoord = new ContentPreviewCoordinator(contentPreviewLayout, true);
String action = targetIntent.getAction();
@@ -1395,10 +1401,11 @@
ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate(
R.layout.chooser_grid_preview_file, parent, false);
- // TODO(b/120417119): Disable file copy until after moving to sysui,
- // due to permissions issues
- //((ViewGroup) contentPreviewLayout.findViewById(R.id.chooser_action_row))
- // .addView(createCopyButton());
+ final ViewGroup actionRow =
+ (ViewGroup) contentPreviewLayout.findViewById(R.id.chooser_action_row);
+ //TODO(b/120417119): addActionButton(actionRow, createCopyButton());
+ addActionButton(actionRow, createNearbyButton(targetIntent));
+
String action = targetIntent.getAction();
if (Intent.ACTION_SEND.equals(action)) {
diff --git a/core/java/com/android/internal/inputmethod/StartInputReason.java b/core/java/com/android/internal/inputmethod/StartInputReason.java
index a01c459..a4eaa21 100644
--- a/core/java/com/android/internal/inputmethod/StartInputReason.java
+++ b/core/java/com/android/internal/inputmethod/StartInputReason.java
@@ -50,8 +50,9 @@
int WINDOW_FOCUS_GAIN = 1;
/**
* {@link android.view.Window} gained focus but there is no {@link android.view.View} that is
- * eligible to have IME focus. {@link android.view.inputmethod.InputMethodManager} just reports
- * this window focus change event.
+ * eligible to have IME focus, or the focused view is same as current served view and its
+ * input connection remains. {@link android.view.inputmethod.InputMethodManager} just reports
+ * this window focus change event to sync IME input target for system.
*/
int WINDOW_FOCUS_GAIN_REPORT_ONLY = 2;
/**
diff --git a/core/java/com/android/internal/util/SyncResultReceiver.java b/core/java/com/android/internal/util/SyncResultReceiver.java
index 00e9101..6b13582 100644
--- a/core/java/com/android/internal/util/SyncResultReceiver.java
+++ b/core/java/com/android/internal/util/SyncResultReceiver.java
@@ -182,7 +182,7 @@
}
/** @hide */
- public static final class TimeoutException extends RuntimeException {
+ public static final class TimeoutException extends Exception {
private TimeoutException(String msg) {
super(msg);
}
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index 1f2ae5f..7c7d931 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -21,6 +21,10 @@
import static com.android.internal.widget.MessagingPropertyAnimator.ALPHA_IN;
import static com.android.internal.widget.MessagingPropertyAnimator.ALPHA_OUT;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ValueAnimator;
import android.annotation.AttrRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -36,6 +40,7 @@
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
+import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.Parcelable;
@@ -80,7 +85,7 @@
private static final float COLOR_SHIFT_AMOUNT = 60;
/**
- * Pattren for filter some ingonable characters.
+ * Pattern for filter some ignorable characters.
* p{Z} for any kind of whitespace or invisible separator.
* p{C} for any kind of punctuation character.
*/
@@ -93,8 +98,12 @@
public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f);
public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
+ public static final Interpolator OVERSHOOT = new PathInterpolator(0.4f, 0f, 0.2f, 1.4f);
public static final OnLayoutChangeListener MESSAGING_PROPERTY_ANIMATOR
= new MessagingPropertyAnimator();
+ public static final int IMPORTANCE_ANIM_GROW_DURATION = 250;
+ public static final int IMPORTANCE_ANIM_SHRINK_DURATION = 200;
+ public static final int IMPORTANCE_ANIM_SHRINK_DELAY = 25;
private List<MessagingMessage> mMessages = new ArrayList<>();
private List<MessagingMessage> mHistoricMessages = new ArrayList<>();
private MessagingLinearLayout mMessagingLinearLayout;
@@ -331,14 +340,74 @@
mNameReplacement = nameReplacement;
}
- /**
- * Sets this conversation as "important", adding some additional UI treatment.
- */
+ /** Sets this conversation as "important", adding some additional UI treatment. */
@RemotableViewMethod
public void setIsImportantConversation(boolean isImportantConversation) {
+ setIsImportantConversation(isImportantConversation, false);
+ }
+
+ /** @hide **/
+ public void setIsImportantConversation(boolean isImportantConversation, boolean animate) {
mImportantConversation = isImportantConversation;
- mImportanceRingView.setVisibility(isImportantConversation
- && mIcon.getVisibility() != GONE ? VISIBLE : GONE);
+ mImportanceRingView.setVisibility(isImportantConversation && mIcon.getVisibility() != GONE
+ ? VISIBLE : GONE);
+
+ if (animate && isImportantConversation) {
+ GradientDrawable ring = (GradientDrawable) mImportanceRingView.getDrawable();
+ ring.mutate();
+ GradientDrawable bg = (GradientDrawable) mConversationIconBadgeBg.getDrawable();
+ bg.mutate();
+ int ringColor = getResources()
+ .getColor(R.color.conversation_important_highlight);
+ int standardThickness = getResources()
+ .getDimensionPixelSize(R.dimen.importance_ring_stroke_width);
+ int largeThickness = getResources()
+ .getDimensionPixelSize(R.dimen.importance_ring_anim_max_stroke_width);
+ int standardSize = getResources().getDimensionPixelSize(
+ R.dimen.importance_ring_size);
+ int baseSize = standardSize - standardThickness * 2;
+ int bgSize = getResources()
+ .getDimensionPixelSize(R.dimen.conversation_icon_size_badged);
+
+ ValueAnimator.AnimatorUpdateListener animatorUpdateListener = animation -> {
+ int strokeWidth = Math.round((float) animation.getAnimatedValue());
+ ring.setStroke(strokeWidth, ringColor);
+ int newSize = baseSize + strokeWidth * 2;
+ ring.setSize(newSize, newSize);
+ mImportanceRingView.invalidate();
+ };
+
+ ValueAnimator growAnimation = ValueAnimator.ofFloat(0, largeThickness);
+ growAnimation.setInterpolator(LINEAR_OUT_SLOW_IN);
+ growAnimation.setDuration(IMPORTANCE_ANIM_GROW_DURATION);
+ growAnimation.addUpdateListener(animatorUpdateListener);
+
+ ValueAnimator shrinkAnimation =
+ ValueAnimator.ofFloat(largeThickness, standardThickness);
+ shrinkAnimation.setDuration(IMPORTANCE_ANIM_SHRINK_DURATION);
+ shrinkAnimation.setStartDelay(IMPORTANCE_ANIM_SHRINK_DELAY);
+ shrinkAnimation.setInterpolator(OVERSHOOT);
+ shrinkAnimation.addUpdateListener(animatorUpdateListener);
+ shrinkAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ // Shrink the badge bg so that it doesn't peek behind the animation
+ bg.setSize(baseSize, baseSize);
+ mConversationIconBadgeBg.invalidate();
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ // Reset bg back to normal size
+ bg.setSize(bgSize, bgSize);
+ mConversationIconBadgeBg.invalidate();
+ }
+ });
+
+ AnimatorSet anims = new AnimatorSet();
+ anims.playSequentially(growAnimation, shrinkAnimation);
+ anims.start();
+ }
}
public boolean isImportantConversation() {
@@ -1176,7 +1245,6 @@
}
private void updateContentEndPaddings() {
-
// Let's make sure the conversation header can't run into the expand button when we're
// collapsed and update the paddings of the content
int headerPaddingEnd;
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 5c444bd..9eede83 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1359,7 +1359,13 @@
}
closedir(dir);
- bool legacySymlinkCreated = false;
+ // Prepare default dirs for user 0 as user 0 always exists.
+ int result = symlink("/data/data", "/data/user/0");
+ if (result != 0) {
+ fail_fn(CREATE_ERROR("Failed to create symlink /data/user/0 %s", strerror(errno)));
+ }
+ PrepareDirIfNotPresent("/data/user_de/0", DEFAULT_DATA_DIR_PERMISSION,
+ AID_ROOT, AID_ROOT, fail_fn);
for (int i = 0; i < size; i += 3) {
std::string const & packageName = merged_data_info_list[i];
@@ -1400,17 +1406,8 @@
char internalDeUserPath[PATH_MAX];
snprintf(internalCeUserPath, PATH_MAX, "/data/user/%d", userId);
snprintf(internalDeUserPath, PATH_MAX, "/data/user_de/%d", userId);
- // If it's user 0, create a symlink /data/user/0 -> /data/data,
- // otherwise create /data/user/$USER
+ // If it's not user 0, create /data/user/$USER.
if (userId == 0) {
- if (!legacySymlinkCreated) {
- legacySymlinkCreated = true;
- int result = symlink(internalLegacyCePath, internalCeUserPath);
- if (result != 0) {
- fail_fn(CREATE_ERROR("Failed to create symlink %s %s", internalCeUserPath,
- strerror(errno)));
- }
- }
actualCePath = internalLegacyCePath;
} else {
PrepareDirIfNotPresent(internalCeUserPath, DEFAULT_DATA_DIR_PERMISSION,
@@ -1587,10 +1584,6 @@
// Fuse is ready, so we can start using fuse path.
int size = (pkg_data_info_list != nullptr) ? env->GetArrayLength(pkg_data_info_list) : 0;
- if (size == 0) {
- fail_fn(CREATE_ERROR("Data package list cannot be empty"));
- }
-
// Create tmpfs on Android/obb and Android/data so these 2 dirs won't enter fuse anymore.
std::string androidObbDir = StringPrintf("/storage/emulated/%d/Android/obb", user_id);
MountAppDataTmpFs(androidObbDir, fail_fn);
diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto
index ecb4193..8e4006a 100644
--- a/core/proto/android/service/notification.proto
+++ b/core/proto/android/service/notification.proto
@@ -274,4 +274,74 @@
// Next Tag: 2
message NotificationRemoteViewsProto {
repeated PackageRemoteViewInfoProto package_remote_view_info = 1;
-}
\ No newline at end of file
+}
+
+/**
+ * Atom that represents an item in the list of Do Not Disturb rules, pulled from
+ * NotificationManagerService.java.
+ */
+message DNDModeProto {
+ enum Mode {
+ ROOT_CONFIG = -1; // Used to distinguish the config (one per user) from the rules.
+ ZEN_MODE_OFF = 0;
+ ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1;
+ ZEN_MODE_NO_INTERRUPTIONS = 2;
+ ZEN_MODE_ALARMS = 3;
+ }
+ optional int32 user = 1; // Android user ID (0, 1, 10, ...)
+ optional bool enabled = 2; // true for ROOT_CONFIG if a manualRule is enabled
+ optional bool channels_bypassing = 3; // only valid for ROOT_CONFIG
+ optional Mode zen_mode = 4;
+ // id is one of the system default rule IDs, or empty
+ // May also be "MANUAL_RULE" to indicate app-activation of the manual rule.
+ optional string id = 5;
+ optional int32 uid = 6; // currently only SYSTEM_UID or 0 for other
+ optional DNDPolicyProto policy = 7;
+}
+
+/**
+ * Atom that represents a Do Not Disturb policy, an optional detail proto for DNDModeProto.
+ */
+message DNDPolicyProto {
+ enum State {
+ STATE_UNSET = 0;
+ STATE_ALLOW = 1;
+ STATE_DISALLOW = 2;
+ }
+ optional State calls = 1;
+ optional State repeat_callers = 2;
+ optional State messages = 3;
+ optional State conversations = 4;
+ optional State reminders = 5;
+ optional State events = 6;
+ optional State alarms = 7;
+ optional State media = 8;
+ optional State system = 9;
+ optional State fullscreen = 10;
+ optional State lights = 11;
+ optional State peek = 12;
+ optional State status_bar = 13;
+ optional State badge = 14;
+ optional State ambient = 15;
+ optional State notification_list = 16;
+
+ enum PeopleType {
+ PEOPLE_UNSET = 0;
+ PEOPLE_ANYONE = 1;
+ PEOPLE_CONTACTS = 2;
+ PEOPLE_STARRED = 3;
+ PEOPLE_NONE = 4;
+ }
+
+ optional PeopleType allow_calls_from = 17;
+ optional PeopleType allow_messages_from = 18;
+
+ enum ConversationType {
+ CONV_UNSET = 0;
+ CONV_ANYONE = 1;
+ CONV_IMPORTANT = 2;
+ CONV_NONE = 3;
+ }
+
+ optional ConversationType allow_conversations_from = 19;
+}
diff --git a/core/res/res/drawable/conversation_badge_background.xml b/core/res/res/drawable/conversation_badge_background.xml
index 0dd0dcd..9e6405d 100644
--- a/core/res/res/drawable/conversation_badge_background.xml
+++ b/core/res/res/drawable/conversation_badge_background.xml
@@ -22,7 +22,7 @@
android:color="#ffffff"/>
<size
- android:width="26dp"
- android:height="26dp"/>
+ android:width="20dp"
+ android:height="20dp"/>
</shape>
diff --git a/core/res/res/drawable/conversation_badge_ring.xml b/core/res/res/drawable/conversation_badge_ring.xml
index 11ba8ad..eee53d1 100644
--- a/core/res/res/drawable/conversation_badge_ring.xml
+++ b/core/res/res/drawable/conversation_badge_ring.xml
@@ -16,17 +16,18 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="oval">
-
- <solid
- android:color="@color/transparent"/>
+ android:shape="oval"
+>
+ <solid android:color="@color/transparent" />
<stroke
android:color="@color/conversation_important_highlight"
- android:width="2dp"/>
+ android:width="@dimen/importance_ring_stroke_width"
+ />
<size
- android:width="26dp"
- android:height="26dp"/>
+ android:width="@dimen/importance_ring_size"
+ android:height="@dimen/importance_ring_size"
+ />
</shape>
diff --git a/core/res/res/layout/chooser_grid_preview_text.xml b/core/res/res/layout/chooser_grid_preview_text.xml
index 0029174..1d18648 100644
--- a/core/res/res/layout/chooser_grid_preview_text.xml
+++ b/core/res/res/layout/chooser_grid_preview_text.xml
@@ -44,6 +44,8 @@
android:ellipsize="end"
android:fontFamily="@android:string/config_headlineFontFamily"
android:textColor="?android:attr/textColorPrimary"
+ android:textAlignment="gravity"
+ android:textDirection="locale"
android:maxLines="2"
android:focusable="true"/>
@@ -90,6 +92,8 @@
android:layout_gravity="center_vertical"
android:ellipsize="end"
android:maxLines="2"
+ android:textAlignment="gravity"
+ android:textDirection="locale"
android:textAppearance="@style/TextAppearance.DeviceDefault.WindowTitle"
android:fontFamily="@android:string/config_headlineFontFamily"/>
</LinearLayout>
diff --git a/core/res/res/layout/notification_template_material_conversation.xml b/core/res/res/layout/notification_template_material_conversation.xml
index 9a9d8b9..d385794 100644
--- a/core/res/res/layout/notification_template_material_conversation.xml
+++ b/core/res/res/layout/notification_template_material_conversation.xml
@@ -38,6 +38,8 @@
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:clipToPadding="false"
android:layout_gravity="top|center_horizontal"
>
@@ -63,13 +65,17 @@
android:layout_height="@dimen/conversation_icon_size_badged"
android:layout_marginLeft="@dimen/conversation_badge_side_margin"
android:layout_marginTop="@dimen/conversation_badge_side_margin"
+ android:clipChildren="false"
+ android:clipToPadding="false"
>
<com.android.internal.widget.CachingIconView
android:id="@+id/conversation_icon_badge_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:layout_gravity="center"
android:src="@drawable/conversation_badge_background"
android:forceHasOverlappingRendering="false"
+ android:scaleType="center"
/>
<com.android.internal.widget.CachingIconView
android:id="@+id/icon"
@@ -81,11 +87,14 @@
/>
<com.android.internal.widget.CachingIconView
android:id="@+id/conversation_icon_badge_ring"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
android:src="@drawable/conversation_badge_ring"
android:visibility="gone"
android:forceHasOverlappingRendering="false"
+ android:clipToPadding="false"
+ android:scaleType="center"
/>
</FrameLayout>
</FrameLayout>
@@ -132,7 +141,7 @@
android:id="@+id/conversation_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_conversation_header_separating_margin"
android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Title"
android:textSize="16sp"
android:singleLine="true"
@@ -145,8 +154,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?attr/notificationHeaderTextAppearance"
- android:layout_marginStart="@dimen/notification_header_separating_margin"
- android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_conversation_header_separating_margin"
android:text="@string/notification_header_divider_symbol"
android:layout_gravity="center"
android:paddingTop="1sp"
@@ -161,7 +170,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
- android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_conversation_header_separating_margin"
android:paddingTop="1sp"
android:singleLine="true"
/>
@@ -171,8 +181,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?attr/notificationHeaderTextAppearance"
- android:layout_marginStart="@dimen/notification_header_separating_margin"
- android:layout_marginEnd="@dimen/notification_header_separating_margin"
+ android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
+ android:layout_marginEnd="@dimen/notification_conversation_header_separating_margin"
android:text="@string/notification_header_divider_symbol"
android:layout_gravity="center"
android:paddingTop="1sp"
@@ -186,7 +196,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
- android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_marginStart="@dimen/notification_conversation_header_separating_margin"
android:paddingTop="1sp"
android:showRelative="true"
android:singleLine="true"
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 1a8c129..8272fed 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -1786,7 +1786,7 @@
<string name="managed_profile_label_badge" msgid="6762559569999499495">"<xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2.º <xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3.º <xliff:g id="LABEL">%1$s</xliff:g> do traballo"</string>
- <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Solicitar PIN para soltar fixación"</string>
+ <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Solicitar PIN para deixar de fixar"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Solicitar un padrón de desbloqueo antes de deixar de fixar a pantalla"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Solicitar un contrasinal para deixar de fixar a pantalla"</string>
<string name="package_installed_device_owner" msgid="7035926868974878525">"Instalado polo teu administrador"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 2877e80..11683ae 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1786,7 +1786,7 @@
<string name="managed_profile_label_badge" msgid="6762559569999499495">"Ажлын <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_2" msgid="5673187309555352550">"2 дахь ажил <xliff:g id="LABEL">%1$s</xliff:g>"</string>
<string name="managed_profile_label_badge_3" msgid="6882151970556391957">"3 дахь ажил <xliff:g id="LABEL">%1$s</xliff:g>"</string>
- <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Тогтоосныг суллахаас өмнө PIN асуух"</string>
+ <string name="lock_to_app_unlock_pin" msgid="3890940811866290782">"Бэхэлснийг болиулахаасаа өмнө PIN асуух"</string>
<string name="lock_to_app_unlock_pattern" msgid="2694204070499712503">"Тогтоосныг суллахаас өмнө түгжээ тайлах хээ асуух"</string>
<string name="lock_to_app_unlock_password" msgid="9126722403506560473">"Тогтоосныг суллахаас өмнө нууц үг асуух"</string>
<string name="package_installed_device_owner" msgid="7035926868974878525">"Таны админ суулгасан"</string>
@@ -1841,7 +1841,7 @@
<string name="zen_mode_default_weeknights_name" msgid="7902108149994062847">"Ажлын өдрийн шөнө"</string>
<string name="zen_mode_default_weekends_name" msgid="4707200272709377930">"Амралтын өдөр"</string>
<string name="zen_mode_default_events_name" msgid="2280682960128512257">"Үйл явдал"</string>
- <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Идэвхгүй"</string>
+ <string name="zen_mode_default_every_night_name" msgid="1467765312174275823">"Унтлагын цаг"</string>
<string name="muted_by" msgid="91464083490094950">"<xliff:g id="THIRD_PARTY">%1$s</xliff:g> зарим дууны дууг хааж байна"</string>
<string name="system_error_wipe_data" msgid="5910572292172208493">"Таны төхөөрөмжид дотоод алдаа байна.Та төхөөрөмжөө үйлдвэрээс гарсан төлөвт шилжүүлэх хүртэл таны төхөөрөмж чинь тогтворгүй байж болох юм."</string>
<string name="system_error_manufacturer" msgid="703545241070116315">"Таны төхөөрөмжид дотоод алдаа байна. Дэлгэрэнгүй мэдээлэл авахыг хүсвэл үйлдвэрлэгчтэйгээ холбоо барина уу."</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 1f72b8b..d910fc0 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -1551,7 +1551,7 @@
<string name="activity_resolver_use_once" msgid="948462794469672658">"တစ်ခါတည်း"</string>
<string name="activity_resolver_work_profiles_support" msgid="4071345609235361269">"%1$s က အလုပ်ပရိုဖိုင်ကို မပံ့ပိုးပါ။"</string>
<string name="default_audio_route_name" product="tablet" msgid="367936735632195517">"တက်ဘလက်"</string>
- <string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"တီဗွီ"</string>
+ <string name="default_audio_route_name" product="tv" msgid="4908971385068087367">"TV"</string>
<string name="default_audio_route_name" product="default" msgid="9213546147739983977">"ဖုန်း"</string>
<string name="default_audio_route_name_dock_speakers" msgid="1551166029093995289">"အထိုင်ရှိသော စပီကာများ"</string>
<string name="default_audio_route_name_hdmi" msgid="5474470558160717850">"HDMI"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 1739453..b1c4fbb 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -951,11 +951,11 @@
<string name="autofill_area" msgid="8289022370678448983">"Gebied"</string>
<string name="autofill_emirate" msgid="2544082046790551168">"Emiraat"</string>
<string name="permlab_readHistoryBookmarks" msgid="9102293913842539697">"je webbladwijzers en -geschiedenis lezen"</string>
- <string name="permdesc_readHistoryBookmarks" msgid="2323799501008967852">"Hiermee kan de app de geschiedenis lezen van alle URL\'s die in de systeemeigen browser zijn bezocht, en alle bladwijzers in de systeemeigen browser. Let op: deze toestemming kan niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
+ <string name="permdesc_readHistoryBookmarks" msgid="2323799501008967852">"Hiermee kan de app de geschiedenis lezen van alle URL\'s die in de systeemeigen browser zijn bezocht, en alle bookmarks in de systeemeigen browser. Let op: deze toestemming kan niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
<string name="permlab_writeHistoryBookmarks" msgid="6090259925187986937">"webbladwijzers en -geschiedenis schrijven"</string>
- <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"Hiermee kan de app de webgeschiedenis wijzigen in de systeemeigen browser en de bladwijzers die zijn opgeslagen op je tablet. Deze toestemming kan niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden.."</string>
- <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"Hiermee kan de app de browsergeschiedenis of opgeslagen bladwijzers bewerken op je Android TV-apparaat. Hierdoor kan de app mogelijk browsergegevens wissen of aanpassen. Opmerking: Dit recht kan niet worden afgedwongen door andere browsers of andere apps met internetmogelijkheden."</string>
- <string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"Hiermee kan de app de webgeschiedenis wijzigen in de systeemeigen browser en de bladwijzers die zijn opgeslagen op je telefoon. Deze toestemming kan niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"Hiermee kan de app de webgeschiedenis wijzigen in de systeemeigen browser en de bookmarks die zijn opgeslagen op je tablet. Deze toestemming kan niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden.."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"Hiermee kan de app de browsergeschiedenis of opgeslagen bookmarks bewerken op je Android TV-apparaat. Hierdoor kan de app mogelijk browsergegevens wissen of aanpassen. Opmerking: Dit recht kan niet worden afgedwongen door andere browsers of andere apps met internetmogelijkheden."</string>
+ <string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"Hiermee kan de app de webgeschiedenis wijzigen in de systeemeigen browser en de bookmarks die zijn opgeslagen op je telefoon. Deze toestemming kan niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
<string name="permlab_setAlarm" msgid="1158001610254173567">"een wekker instellen"</string>
<string name="permdesc_setAlarm" msgid="2185033720060109640">"Hiermee kan de app een wekker instellen in een geïnstalleerde wekker-app. Deze functie wordt door sommige wekker-apps niet geïmplementeerd."</string>
<string name="permlab_addVoicemail" msgid="4770245808840814471">"voicemail toevoegen"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index 4224523..5986e76 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -787,7 +787,7 @@
<string name="imProtocolYahoo" msgid="5373338758093392231">"Yahoo"</string>
<string name="imProtocolSkype" msgid="1486297589164830043">"Skype"</string>
<string name="imProtocolQq" msgid="7254708777029006592">"QQ"</string>
- <string name="imProtocolGoogleTalk" msgid="9194016024343166782">"ହ୍ୟାଙ୍ଗଆଉଟ୍ସ"</string>
+ <string name="imProtocolGoogleTalk" msgid="9194016024343166782">"Hangouts"</string>
<string name="imProtocolIcq" msgid="2410325380427389521">"ICQ"</string>
<string name="imProtocolJabber" msgid="7919269388889582015">"Jabber"</string>
<string name="imProtocolNetMeeting" msgid="4985002408136148256">"NetMeeting"</string>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 59bb052..4ee9192 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -273,6 +273,9 @@
<!-- The margin before and after each of the items in the notification header. -->
<dimen name="notification_header_separating_margin">2dp</dimen>
+ <!-- The margin before and after each of the items in the conversation header. -->
+ <dimen name="notification_conversation_header_separating_margin">4dp</dimen>
+
<!-- The absolute size of the notification expand icon. -2 for wrap_content. -->
<dimen name="notification_header_expand_icon_size">-2px</dimen>
@@ -719,10 +722,16 @@
<!-- The width of the protection of the face pile layout when expanded-->
<dimen name="conversation_face_pile_protection_width_expanded">1dp</dimen>
<!-- The padding of the expanded message container-->
- <dimen name="expanded_group_conversation_message_padding">14dp</dimen>
+ <dimen name="expanded_group_conversation_message_padding">17dp</dimen>
+ <!-- The stroke width of the ring used to visually mark a conversation as important -->
+ <dimen name="importance_ring_stroke_width">2dp</dimen>
+ <!-- The maximum stroke width used for the animation shown when a conversation is marked as important -->
+ <dimen name="importance_ring_anim_max_stroke_width">10dp</dimen>
+ <!-- The size of the importance ring -->
+ <dimen name="importance_ring_size">20dp</dimen>
<!-- The top padding of the conversation icon container in the regular state-->
- <dimen name="conversation_icon_container_top_padding">9dp</dimen>
+ <dimen name="conversation_icon_container_top_padding">12dp</dimen>
<!-- The top padding of the conversation icon container when the avatar is small-->
<dimen name="conversation_icon_container_top_padding_small_avatar">17.5dp</dimen>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ab4005b..23ae1e7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3903,6 +3903,12 @@
<java-symbol type="array" name="config_defaultImperceptibleKillingExemptionPkgs" />
<java-symbol type="array" name="config_defaultImperceptibleKillingExemptionProcStates" />
+ <java-symbol type="color" name="conversation_important_highlight" />
+ <java-symbol type="dimen" name="importance_ring_stroke_width" />
+ <java-symbol type="dimen" name="importance_ring_anim_max_stroke_width" />
+ <java-symbol type="dimen" name="importance_ring_size" />
+ <java-symbol type="dimen" name="conversation_icon_size_badged" />
+
<java-symbol type="id" name="header_icon_container" />
<java-symbol type="attr" name="notificationHeaderTextAppearance" />
<java-symbol type="string" name="conversation_single_line_name_display" />
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 70917e7..d5733e3 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -39,7 +39,7 @@
<!-- Albania: 5 digits, known short codes listed -->
<shortcode country="al" pattern="\\d{5}" premium="15191|55[56]00" />
- <!-- Argentia: 5 digits, known short codes listed -->
+ <!-- Argentina: 5 digits, known short codes listed -->
<shortcode country="ar" pattern="\\d{5}" free="11711|28291" />
<!-- Armenia: 3-4 digits, emergency numbers 10[123] -->
@@ -70,7 +70,7 @@
<shortcode country="by" pattern="\\d{4}" premium="3336|4161|444[4689]|501[34]|7781" />
<!-- Canada: 5-6 digits -->
- <shortcode country="ca" pattern="\\d{5,6}" premium="60999|88188|43030" standard="244444" />
+ <shortcode country="ca" pattern="\\d{5,6}" premium="60999|88188|43030" standard="244444" free="455677" />
<!-- Switzerland: 3-5 digits: http://www.swisscom.ch/fxres/kmu/thirdpartybusiness_code_of_conduct_en.pdf -->
<shortcode country="ch" pattern="[2-9]\\d{2,4}" premium="543|83111|30118" free="98765|30075|30047" />
diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
index 25f9413..bf7f339 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
@@ -16,6 +16,9 @@
package android.view;
+import static android.view.InsetsController.ANIMATION_TYPE_NONE;
+import static android.view.InsetsController.ANIMATION_TYPE_USER;
+import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.WindowInsets.Type.statusBars;
@@ -23,14 +26,18 @@
import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
import android.app.Instrumentation;
import android.content.Context;
import android.graphics.Point;
+import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl.Transaction;
import android.view.WindowManager.BadTokenException;
@@ -122,6 +129,48 @@
}
@Test
+ public void testPendingStates() {
+ InsetsState state = new InsetsState();
+ InsetsController controller = mock(InsetsController.class);
+ InsetsSourceConsumer consumer = new InsetsSourceConsumer(
+ ITYPE_IME, state, null, controller);
+
+ when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_NONE);
+
+ InsetsSource source = new InsetsSource(ITYPE_IME);
+ source.setFrame(0, 1, 2, 3);
+ consumer.updateSource(new InsetsSource(source));
+
+ when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_USER);
+
+ // While we're animating, updates are delayed
+ source.setFrame(4, 5, 6, 7);
+ consumer.updateSource(new InsetsSource(source));
+ assertEquals(new Rect(0, 1, 2, 3), state.peekSource(ITYPE_IME).getFrame());
+
+ // Finish the animation, now the pending frame should be applied
+ when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_NONE);
+ assertTrue(consumer.notifyAnimationFinished());
+ assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame());
+
+ when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_USER);
+
+ // Animating again, updates are delayed
+ source.setFrame(8, 9, 10, 11);
+ consumer.updateSource(new InsetsSource(source));
+ assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame());
+
+ // Updating with the current frame triggers a different code path, verify this clears
+ // the pending 8, 9, 10, 11 frame:
+ source.setFrame(4, 5, 6, 7);
+ consumer.updateSource(new InsetsSource(source));
+
+ when(controller.getAnimationType(anyInt())).thenReturn(ANIMATION_TYPE_NONE);
+ assertFalse(consumer.notifyAnimationFinished());
+ assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame());
+ }
+
+ @Test
public void testRestore() {
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
mConsumer.setControl(null, new int[1], new int[1]);
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index daaf31a..cd93eeb 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -27,6 +27,8 @@
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
import static android.view.WindowInsets.Type.ime;
+import static android.view.WindowInsets.Type.navigationBars;
+import static android.view.WindowInsets.Type.statusBars;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
@@ -341,6 +343,26 @@
}
}
+ @Test
+ public void testCalculateUncontrollableInsets() throws Exception {
+ try (InsetsModeSession session = new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+ mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 200, 100));
+ mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
+ mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 200, 300));
+ mState.getSource(ITYPE_IME).setVisible(true);
+ mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(100, 0, 200, 300));
+ mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true);
+
+ mState.setDisplayFrame(new Rect(0, 0, 200, 300));
+ assertEquals(0,
+ mState.calculateUncontrollableInsetsFromFrame(new Rect(0, 0, 200, 300)));
+ assertEquals(statusBars() | ime(),
+ mState.calculateUncontrollableInsetsFromFrame(new Rect(0, 50, 200, 250)));
+ assertEquals(navigationBars(),
+ mState.calculateUncontrollableInsetsFromFrame(new Rect(50, 0, 150, 300)));
+ }
+ }
+
private void assertEqualsAndHashCode() {
assertEquals(mState, mState2);
assertEquals(mState.hashCode(), mState2.hashCode());
diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp
index 1b1a624..d6542de 100644
--- a/data/etc/car/Android.bp
+++ b/data/etc/car/Android.bp
@@ -122,6 +122,13 @@
}
prebuilt_etc {
+ name: "privapp_whitelist_com.android.car.bugreport",
+ sub_dir: "permissions",
+ src: "com.android.car.bugreport.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
name: "privapp_whitelist_com.google.android.car.kitchensink",
sub_dir: "permissions",
src: "com.google.android.car.kitchensink.xml",
diff --git a/data/etc/car/com.android.car.bugreport.xml b/data/etc/car/com.android.car.bugreport.xml
new file mode 100644
index 0000000..432a838
--- /dev/null
+++ b/data/etc/car/com.android.car.bugreport.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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
+ -->
+<permissions>
+ <privapp-permissions package="com.android.car.bugreport">
+ <permission name="android.permission.DUMP"/>
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ <permission name="android.permission.READ_LOGS"/>
+ <permission name="android.permission.MANAGE_USERS"/>
+ </privapp-permissions>
+ </permissions>
diff --git a/data/etc/preinstalled-packages-platform.xml b/data/etc/preinstalled-packages-platform.xml
index 17e1f2e..6255584 100644
--- a/data/etc/preinstalled-packages-platform.xml
+++ b/data/etc/preinstalled-packages-platform.xml
@@ -17,7 +17,9 @@
<!--
This XML file declares which system packages should be initially installed for new users based on
their user type. All system packages on the device should ideally have an entry in an xml file
-(keyed by its manifest name).
+(keyed by its manifest name), except auto-generated rro packages. Auto-generated RRO packages
+(package name ends with ".auto_generated_rro_product__" or ".auto_generated_rro_vendor__")
+will be installed for new users according to corresponding overlay target packages.
Base user-types (every user will be at least one of these types) are:
SYSTEM (user 0)
@@ -51,7 +53,7 @@
2. For a system package to be pre-installed on all human users (e.g. a web browser), i.e. to be
-installed on any user of type type FULL or PROFILE (since this covers all human users):
+installed on any user of type FULL or PROFILE (since this covers all human users):
<install-in-user-type package="com.android.example">
<install-in user-type="FULL" />
diff --git a/identity/java/android/security/identity/IdentityCredential.java b/identity/java/android/security/identity/IdentityCredential.java
index b351b3d..493c85a 100644
--- a/identity/java/android/security/identity/IdentityCredential.java
+++ b/identity/java/android/security/identity/IdentityCredential.java
@@ -167,25 +167,14 @@
* IntentToRetain = bool
* </pre>
*
- * <p>If the {@code sessionTranscript} parameter is not {@code null}, it must contain CBOR
- * data conforming to the following CDDL schema:
- *
- * <pre>
- * SessionTranscript = [
- * DeviceEngagementBytes,
- * EReaderKeyBytes
- * ]
- *
- * DeviceEngagementBytes = #6.24(bstr .cbor DeviceEngagement) ; Bytes of DeviceEngagement
- * EReaderKeyBytes = #6.24(bstr .cbor EReaderKey.Pub) ; Bytes of EReaderKey.pub
- *
- * EReaderKey.Pub = COSE_Key ; Ephemeral public key provided by reader
- * </pre>
- *
- * <p>where a {@code COSE_Key} structure for the public part of the key-pair previously
- * generated by {@link #createEphemeralKeyPair()} must appear somewhere in
- * {@code DeviceEngagement} and the X and Y coordinates must both be present
- * in uncompressed form.
+ * <p>If the {@code sessionTranscript} parameter is not {@code null}, the X and Y coordinates
+ * of the public part of the key-pair previously generated by {@link #createEphemeralKeyPair()}
+ * must appear somewhere in the bytes of the CBOR. Each of these coordinates must appear
+ * encoded with the most significant bits first and use the exact amount of bits indicated by
+ * the key size of the ephemeral keys. For example, if the ephemeral key is using the P-256
+ * curve then the 32 bytes for the X coordinate encoded with the most significant bits first
+ * must appear somewhere in {@code sessionTranscript} and ditto for the 32 bytes for the Y
+ * coordinate.
*
* <p>If {@code readerAuth} is not {@code null} it must be the bytes of a {@code COSE_Sign1}
* structure as defined in RFC 8152. For the payload nil shall be used and the
diff --git a/identity/java/android/security/identity/WritableIdentityCredential.java b/identity/java/android/security/identity/WritableIdentityCredential.java
index c7aa328..305d0ea 100644
--- a/identity/java/android/security/identity/WritableIdentityCredential.java
+++ b/identity/java/android/security/identity/WritableIdentityCredential.java
@@ -56,10 +56,10 @@
* authority doesn't care about the nature of the security hardware. If called, however, this
* method must be called before {@link #personalize(PersonalizationData)}.
*
- * @param challenge is a byte array whose contents should be unique, fresh and provided by
- * the issuing authority. The value provided is embedded in the attestation
- * extension and enables the issuing authority to verify that the attestation
- * certificate is fresh.
+ * @param challenge is a non-empty byte array whose contents should be unique, fresh and
+ * provided by the issuing authority. The value provided is embedded in the
+ * attestation extension and enables the issuing authority to verify that the
+ * attestation certificate is fresh.
* @return the X.509 certificate for this credential's CredentialKey.
*/
public abstract @NonNull Collection<X509Certificate> getCredentialKeyCertificateChain(
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 9846436..67a040d 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -18,7 +18,6 @@
import android.app.Notification;
import android.app.NotificationManager;
-import android.app.PendingIntent;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -402,13 +401,9 @@
mNiNotificationBuilder.setDefaults(0);
}
- // if not to popup dialog immediately, pending intent will open the dialog
- Intent intent = !mPopupImmediately ? getDlgIntent(notif) : new Intent();
- PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
mNiNotificationBuilder.setTicker(getNotifTicker(notif, mContext))
.setContentTitle(title)
- .setContentText(message)
- .setContentIntent(pi);
+ .setContentText(message);
notificationManager.notifyAsUser(null, notif.notificationId, mNiNotificationBuilder.build(),
UserHandle.ALL);
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index 323bba3..6c40116 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -32,7 +32,7 @@
import com.android.internal.app.IBatteryStats;
import com.android.internal.location.nano.GnssLogsProto.GnssLog;
import com.android.internal.location.nano.GnssLogsProto.PowerMetrics;
-import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.ConcurrentUtils;
import com.android.internal.util.FrameworkStatsLog;
import java.util.ArrayList;
@@ -124,8 +124,6 @@
private long mL5SvStatusReportsUsedInFix;
/** Stats manager service for reporting atoms */
private StatsManager mStatsManager;
- /** Pull atom callback, this is called when atom pull request occurs */
- private StatsPullAtomCallbackImpl mPullAtomCallback;
/* Statds Logging Variables Section End */
public GnssMetrics(Context context, IBatteryStats stats) {
@@ -467,8 +465,8 @@
mConstellationTypes = new boolean[GnssStatus.CONSTELLATION_COUNT];
}
- /** Class for storing statistics */
- private class Statistics {
+ /** Thread-safe class for storing statistics */
+ private static class Statistics {
private int mCount;
private double mSum;
@@ -476,7 +474,7 @@
private long mLongSum;
/** Resets statistics */
- public void reset() {
+ public synchronized void reset() {
mCount = 0;
mSum = 0.0;
mSumSquare = 0.0;
@@ -484,7 +482,7 @@
}
/** Adds an item */
- public void addItem(double item) {
+ public synchronized void addItem(double item) {
mCount++;
mSum += item;
mSumSquare += item * item;
@@ -492,17 +490,17 @@
}
/** Returns number of items added */
- public int getCount() {
+ public synchronized int getCount() {
return mCount;
}
/** Returns mean */
- public double getMean() {
+ public synchronized double getMean() {
return mSum / mCount;
}
/** Returns standard deviation */
- public double getStandardDeviation() {
+ public synchronized double getStandardDeviation() {
double m = mSum / mCount;
m = m * m;
double v = mSumSquare / mCount;
@@ -513,7 +511,7 @@
}
/** Returns long sum */
- public long getLongSum() {
+ public synchronized long getLongSum() {
return mLongSum;
}
}
@@ -623,11 +621,11 @@
}
private void registerGnssStats() {
- mPullAtomCallback = new StatsPullAtomCallbackImpl();
+ StatsPullAtomCallbackImpl pullAtomCallback = new StatsPullAtomCallbackImpl();
mStatsManager.setPullAtomCallback(
FrameworkStatsLog.GNSS_STATS,
null, // use default PullAtomMetadata values
- BackgroundThread.getExecutor(), mPullAtomCallback);
+ ConcurrentUtils.DIRECT_EXECUTOR, pullAtomCallback);
}
/**
diff --git a/media/java/android/media/IMediaRouter2Manager.aidl b/media/java/android/media/IMediaRouter2Manager.aidl
index 5925d38..5113dc2 100644
--- a/media/java/android/media/IMediaRouter2Manager.aidl
+++ b/media/java/android/media/IMediaRouter2Manager.aidl
@@ -24,8 +24,9 @@
* {@hide}
*/
oneway interface IMediaRouter2Manager {
- void notifySessionCreated(int requestId, in RoutingSessionInfo sessionInfo);
- void notifySessionUpdated(in RoutingSessionInfo sessionInfo);
+ void notifySessionCreated(int requestId, in RoutingSessionInfo session);
+ void notifySessionUpdated(in RoutingSessionInfo session);
+ void notifySessionReleased(in RoutingSessionInfo session);
void notifyPreferredFeaturesChanged(String packageName, in List<String> preferredFeatures);
void notifyRoutesAdded(in List<MediaRoute2Info> routes);
void notifyRoutesRemoved(in List<MediaRoute2Info> routes);
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 20e26cd..e767c68 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -399,11 +399,16 @@
Objects.requireNonNull(controller, "controller must not be null");
Objects.requireNonNull(route, "route must not be null");
- // TODO(b/157873496): Check thread-safety, at least check "sRouterLock" for every variable
- if (!mRoutes.containsKey(route.getId())) {
+ boolean routeFound;
+ synchronized (sRouterLock) {
+ // TODO: Check thread-safety
+ routeFound = mRoutes.containsKey(route.getId());
+ }
+ if (!routeFound) {
notifyTransferFailure(route);
return;
}
+
if (controller.getRoutingSessionInfo().getTransferableRoutes().contains(route.getId())) {
controller.transferToRoute(route);
return;
@@ -572,10 +577,6 @@
}
void addRoutesOnHandler(List<MediaRoute2Info> routes) {
- // TODO(b/157874065): When onRoutesAdded is first called,
- // 1) clear mRoutes before adding the routes
- // 2) Call onRouteSelected(system_route, reason_fallback) if previously selected route
- // does not exist anymore. => We may need 'boolean MediaRoute2Info#isSystemRoute()'.
List<MediaRoute2Info> addedRoutes = new ArrayList<>();
synchronized (sRouterLock) {
for (MediaRoute2Info route : routes) {
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index a382c2d..1c2d581 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -25,12 +25,14 @@
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
import android.os.Handler;
+import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.Collections;
@@ -52,6 +54,9 @@
public final class MediaRouter2Manager {
private static final String TAG = "MR2Manager";
private static final Object sLock = new Object();
+ /** @hide */
+ @VisibleForTesting
+ public static final int TRANSFER_TIMEOUT_MS = 30_000;
@GuardedBy("sLock")
private static MediaRouter2Manager sInstance;
@@ -337,30 +342,18 @@
Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
Objects.requireNonNull(route, "route must not be null");
- //TODO(b/157875504): Ignore unknown route.
+ synchronized (mRoutesLock) {
+ if (!mRoutes.containsKey(route.getId())) {
+ Log.w(TAG, "transfer: Ignoring an unknown route id=" + route.getId());
+ notifyTransferFailed(sessionInfo, route);
+ return;
+ }
+ }
+
if (sessionInfo.getTransferableRoutes().contains(route.getId())) {
transferToRoute(sessionInfo, route);
- return;
- }
-
- if (TextUtils.isEmpty(sessionInfo.getClientPackageName())) {
- Log.w(TAG, "transfer: Ignoring transfer without package name.");
- notifyTransferFailed(sessionInfo, route);
- return;
- }
-
- Client client = getOrCreateClient();
- if (client != null) {
- try {
- int requestId = mNextRequestId.getAndIncrement();
- //TODO(b/157875723): Ensure that every request is eventually removed. (Memory leak)
- mTransferRequests.add(new TransferRequest(requestId, sessionInfo, route));
-
- mMediaRouterService.requestCreateSessionWithManager(
- client, requestId, sessionInfo.getClientPackageName(), route);
- } catch (RemoteException ex) {
- Log.e(TAG, "Unable to select media route", ex);
- }
+ } else {
+ requestCreateSession(sessionInfo, route);
}
}
@@ -516,15 +509,15 @@
notifyRequestFailed(reason);
}
- void handleSessionsUpdated(RoutingSessionInfo sessionInfo) {
+ void handleSessionsUpdatedOnHandler(RoutingSessionInfo sessionInfo) {
for (TransferRequest request : mTransferRequests) {
String sessionId = request.mOldSessionInfo.getId();
if (!TextUtils.equals(sessionId, sessionInfo.getId())) {
continue;
}
if (sessionInfo.getSelectedRoutes().contains(request.mTargetRoute.getId())) {
- notifyTransferred(request.mOldSessionInfo, sessionInfo);
mTransferRequests.remove(request);
+ notifyTransferred(request.mOldSessionInfo, sessionInfo);
break;
}
}
@@ -558,6 +551,12 @@
}
}
+ void notifySessionReleased(RoutingSessionInfo session) {
+ for (CallbackRecord record : mCallbackRecords) {
+ record.mExecutor.execute(() -> record.mCallback.onSessionReleased(session));
+ }
+ }
+
void notifyRequestFailed(int reason) {
for (CallbackRecord record : mCallbackRecords) {
record.mExecutor.execute(() -> record.mCallback.onRequestFailed(reason));
@@ -595,7 +594,7 @@
public List<MediaRoute2Info> getSelectedRoutes(@NonNull RoutingSessionInfo sessionInfo) {
Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
- synchronized (sLock) {
+ synchronized (mRoutesLock) {
return sessionInfo.getSelectedRoutes().stream().map(mRoutes::get)
.filter(Objects::nonNull)
.collect(Collectors.toList());
@@ -611,7 +610,7 @@
List<String> selectedRouteIds = sessionInfo.getSelectedRoutes();
- synchronized (sLock) {
+ synchronized (mRoutesLock) {
return sessionInfo.getSelectableRoutes().stream()
.filter(routeId -> !selectedRouteIds.contains(routeId))
.map(mRoutes::get)
@@ -629,7 +628,7 @@
List<String> selectedRouteIds = sessionInfo.getSelectedRoutes();
- synchronized (sLock) {
+ synchronized (mRoutesLock) {
return sessionInfo.getDeselectableRoutes().stream()
.filter(routeId -> selectedRouteIds.contains(routeId))
.map(mRoutes::get)
@@ -725,41 +724,6 @@
}
/**
- * Transfers to a given route for the remote session.
- *
- * @hide
- */
- void transferToRoute(@NonNull RoutingSessionInfo sessionInfo,
- @NonNull MediaRoute2Info route) {
- Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
- Objects.requireNonNull(route, "route must not be null");
-
- if (sessionInfo.getSelectedRoutes().contains(route.getId())) {
- Log.w(TAG, "Ignoring transferring to a route that is already added. route="
- + route);
- return;
- }
-
- if (!sessionInfo.getTransferableRoutes().contains(route.getId())) {
- Log.w(TAG, "Ignoring transferring to a non-transferable route=" + route);
- return;
- }
-
- int requestId = mNextRequestId.getAndIncrement();
- mTransferRequests.add(new TransferRequest(requestId, sessionInfo, route));
-
- Client client = getOrCreateClient();
- if (client != null) {
- try {
- mMediaRouterService.transferToRouteWithManager(
- client, requestId, sessionInfo.getId(), route);
- } catch (RemoteException ex) {
- Log.e(TAG, "transferToRoute: Failed to send a request.", ex);
- }
- }
- }
-
- /**
* Requests releasing a session.
* <p>
* If a session is released, any operation on the session will be ignored.
@@ -784,6 +748,65 @@
}
}
+ /**
+ * Transfers the remote session to the given route.
+ *
+ * @hide
+ */
+ private void transferToRoute(@NonNull RoutingSessionInfo session,
+ @NonNull MediaRoute2Info route) {
+ int requestId = createTransferRequest(session, route);
+
+ Client client = getOrCreateClient();
+ if (client != null) {
+ try {
+ mMediaRouterService.transferToRouteWithManager(
+ client, requestId, session.getId(), route);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "transferToRoute: Failed to send a request.", ex);
+ }
+ }
+ }
+
+ private void requestCreateSession(RoutingSessionInfo oldSession, MediaRoute2Info route) {
+ if (TextUtils.isEmpty(oldSession.getClientPackageName())) {
+ Log.w(TAG, "requestCreateSession: Can't create a session without package name.");
+ notifyTransferFailed(oldSession, route);
+ return;
+ }
+
+ int requestId = createTransferRequest(oldSession, route);
+
+ Client client = getOrCreateClient();
+ if (client != null) {
+ try {
+ mMediaRouterService.requestCreateSessionWithManager(
+ client, requestId, oldSession.getClientPackageName(), route);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "requestCreateSession: Failed to send a request", ex);
+ }
+ }
+ }
+
+ private int createTransferRequest(RoutingSessionInfo session, MediaRoute2Info route) {
+ int requestId = mNextRequestId.getAndIncrement();
+ TransferRequest transferRequest = new TransferRequest(requestId, session, route);
+ mTransferRequests.add(transferRequest);
+
+ Message timeoutMessage =
+ obtainMessage(MediaRouter2Manager::handleTransferTimeout, this, transferRequest);
+ mHandler.sendMessageDelayed(timeoutMessage, TRANSFER_TIMEOUT_MS);
+ return requestId;
+ }
+
+ private void handleTransferTimeout(TransferRequest request) {
+ boolean removed = mTransferRequests.remove(request);
+ if (removed) {
+ notifyTransferFailed(request.mOldSessionInfo, request.mTargetRoute);
+ }
+ }
+
+
private boolean areSessionsMatched(MediaController mediaController,
RoutingSessionInfo sessionInfo) {
MediaController.PlaybackInfo playbackInfo = mediaController.getPlaybackInfo();
@@ -847,9 +870,16 @@
/**
* Called when a session is changed.
- * @param sessionInfo the updated session
+ * @param session the updated session
*/
- public void onSessionUpdated(@NonNull RoutingSessionInfo sessionInfo) {}
+ public void onSessionUpdated(@NonNull RoutingSessionInfo session) {}
+
+ /**
+ * Called when a session is released.
+ * @param session the released session.
+ * @see #releaseSession(RoutingSessionInfo)
+ */
+ public void onSessionReleased(@NonNull RoutingSessionInfo session) {}
/**
* Called when media is transferred.
@@ -905,7 +935,7 @@
if (!(obj instanceof CallbackRecord)) {
return false;
}
- return mCallback == ((CallbackRecord) obj).mCallback;
+ return mCallback == ((CallbackRecord) obj).mCallback;
}
@Override
@@ -929,15 +959,21 @@
class Client extends IMediaRouter2Manager.Stub {
@Override
- public void notifySessionCreated(int requestId, RoutingSessionInfo sessionInfo) {
+ public void notifySessionCreated(int requestId, RoutingSessionInfo session) {
mHandler.sendMessage(obtainMessage(MediaRouter2Manager::createSessionOnHandler,
- MediaRouter2Manager.this, requestId, sessionInfo));
+ MediaRouter2Manager.this, requestId, session));
}
@Override
- public void notifySessionUpdated(RoutingSessionInfo sessionInfo) {
- mHandler.sendMessage(obtainMessage(MediaRouter2Manager::handleSessionsUpdated,
- MediaRouter2Manager.this, sessionInfo));
+ public void notifySessionUpdated(RoutingSessionInfo session) {
+ mHandler.sendMessage(obtainMessage(MediaRouter2Manager::handleSessionsUpdatedOnHandler,
+ MediaRouter2Manager.this, session));
+ }
+
+ @Override
+ public void notifySessionReleased(RoutingSessionInfo session) {
+ mHandler.sendMessage(obtainMessage(MediaRouter2Manager::notifySessionReleased,
+ MediaRouter2Manager.this, session));
}
@Override
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index 26e65dd..1bf2863 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -16,28 +16,22 @@
package android.media;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.lang.ref.WeakReference;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityThread;
-import android.app.AppOpsManager;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
-import android.media.PlayerBase;
import android.os.Handler;
-import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
-import android.os.Process;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.util.AndroidRuntimeException;
import android.util.Log;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.lang.ref.WeakReference;
+import java.util.concurrent.atomic.AtomicReference;
+
/**
* The SoundPool class manages and plays audio resources for applications.
@@ -122,13 +116,12 @@
private final static String TAG = "SoundPool";
private final static boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private final AtomicReference<EventHandler> mEventHandler = new AtomicReference<>(null);
+
private long mNativeContext; // accessed by native methods
- private EventHandler mEventHandler;
- private SoundPool.OnLoadCompleteListener mOnLoadCompleteListener;
private boolean mHasAppOpsPlayAudio;
- private final Object mLock;
private final AudioAttributes mAttributes;
/**
@@ -159,7 +152,6 @@
if (native_setup(new WeakReference<SoundPool>(this), maxStreams, attributes) != 0) {
throw new RuntimeException("Native setup failed");
}
- mLock = new Object();
mAttributes = attributes;
baseRegisterPlayer();
@@ -491,21 +483,18 @@
* Sets the callback hook for the OnLoadCompleteListener.
*/
public void setOnLoadCompleteListener(OnLoadCompleteListener listener) {
- synchronized(mLock) {
- if (listener != null) {
- // setup message handler
- Looper looper;
- if ((looper = Looper.myLooper()) != null) {
- mEventHandler = new EventHandler(looper);
- } else if ((looper = Looper.getMainLooper()) != null) {
- mEventHandler = new EventHandler(looper);
- } else {
- mEventHandler = null;
- }
- } else {
- mEventHandler = null;
- }
- mOnLoadCompleteListener = listener;
+ if (listener == null) {
+ mEventHandler.set(null);
+ return;
+ }
+
+ Looper looper;
+ if ((looper = Looper.myLooper()) != null) {
+ mEventHandler.set(new EventHandler(looper, listener));
+ } else if ((looper = Looper.getMainLooper()) != null) {
+ mEventHandler.set(new EventHandler(looper, listener));
+ } else {
+ mEventHandler.set(null);
}
}
@@ -525,35 +514,36 @@
@SuppressWarnings("unchecked")
private static void postEventFromNative(Object ref, int msg, int arg1, int arg2, Object obj) {
SoundPool soundPool = ((WeakReference<SoundPool>) ref).get();
- if (soundPool == null)
+ if (soundPool == null) {
return;
-
- if (soundPool.mEventHandler != null) {
- Message m = soundPool.mEventHandler.obtainMessage(msg, arg1, arg2, obj);
- soundPool.mEventHandler.sendMessage(m);
}
+
+ Handler eventHandler = soundPool.mEventHandler.get();
+ if (eventHandler == null) {
+ return;
+ }
+
+ Message message = eventHandler.obtainMessage(msg, arg1, arg2, obj);
+ eventHandler.sendMessage(message);
}
private final class EventHandler extends Handler {
- public EventHandler(Looper looper) {
+ private final OnLoadCompleteListener mOnLoadCompleteListener;
+
+ EventHandler(Looper looper, @NonNull OnLoadCompleteListener onLoadCompleteListener) {
super(looper);
+ mOnLoadCompleteListener = onLoadCompleteListener;
}
@Override
public void handleMessage(Message msg) {
- switch(msg.what) {
- case SAMPLE_LOADED:
- if (DEBUG) Log.d(TAG, "Sample " + msg.arg1 + " loaded");
- synchronized(mLock) {
- if (mOnLoadCompleteListener != null) {
- mOnLoadCompleteListener.onLoadComplete(SoundPool.this, msg.arg1, msg.arg2);
- }
- }
- break;
- default:
+ if (msg.what != SAMPLE_LOADED) {
Log.e(TAG, "Unknown message type " + msg.what);
return;
}
+
+ if (DEBUG) Log.d(TAG, "Sample " + msg.arg1 + " loaded");
+ mOnLoadCompleteListener.onLoadComplete(SoundPool.this, msg.arg1, msg.arg2);
}
}
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index a03b24c..f970b59 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -233,10 +233,12 @@
}
void JMediaCodec::releaseAsync() {
- if (mCodec != NULL) {
- mCodec->releaseAsync();
- }
- mInitStatus = NO_INIT;
+ std::call_once(mAsyncReleaseFlag, [this] {
+ if (mCodec != NULL) {
+ mCodec->releaseAsync(new AMessage(kWhatAsyncReleaseComplete, this));
+ }
+ mInitStatus = NO_INIT;
+ });
}
JMediaCodec::~JMediaCodec() {
@@ -1084,6 +1086,12 @@
handleFrameRenderedNotification(msg);
break;
}
+ case kWhatAsyncReleaseComplete:
+ {
+ mCodec.clear();
+ mLooper->stop();
+ break;
+ }
default:
TRESPASS();
}
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 5c34341..a58f9a7 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -173,6 +173,7 @@
enum {
kWhatCallbackNotify,
kWhatFrameRendered,
+ kWhatAsyncReleaseComplete,
};
jclass mClass;
@@ -185,6 +186,7 @@
bool mGraphicOutput{false};
bool mHasCryptoOrDescrambler{false};
std::once_flag mReleaseFlag;
+ std::once_flag mAsyncReleaseFlag;
sp<AMessage> mCallbackNotification;
sp<AMessage> mOnFrameRenderedNotification;
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
index 1e49f49..9575581 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
@@ -17,6 +17,7 @@
package com.android.mediaroutertest;
import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
+import static android.media.MediaRoute2Info.FEATURE_REMOTE_PLAYBACK;
import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_FIXED;
import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
import static android.media.MediaRoute2ProviderService.REASON_REJECTED;
@@ -28,6 +29,7 @@
import static com.android.mediaroutertest.StubMediaRoute2ProviderService.ROUTE_ID2;
import static com.android.mediaroutertest.StubMediaRoute2ProviderService.ROUTE_ID4_TO_SELECT_AND_DESELECT;
import static com.android.mediaroutertest.StubMediaRoute2ProviderService.ROUTE_ID5_TO_TRANSFER_TO;
+import static com.android.mediaroutertest.StubMediaRoute2ProviderService.ROUTE_ID6_TO_BE_IGNORED;
import static com.android.mediaroutertest.StubMediaRoute2ProviderService.ROUTE_ID_FIXED_VOLUME;
import static com.android.mediaroutertest.StubMediaRoute2ProviderService.ROUTE_ID_SPECIAL_FEATURE;
import static com.android.mediaroutertest.StubMediaRoute2ProviderService.ROUTE_ID_VARIABLE_VOLUME;
@@ -51,6 +53,7 @@
import android.media.RoutingSessionInfo;
import android.os.Bundle;
import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.text.TextUtils;
@@ -79,6 +82,8 @@
private static final int TIMEOUT_MS = 5000;
private static final String TEST_KEY = "test_key";
private static final String TEST_VALUE = "test_value";
+ private static final String TEST_ID_UNKNOWN = "id_unknown";
+ private static final String TEST_NAME_UNKNOWN = "unknown";
private Context mContext;
private MediaRouter2Manager mManager;
@@ -276,17 +281,19 @@
}
@Test
- public void testGetRoutingControllers() throws Exception {
+ public void testGetRoutingSessions() throws Exception {
CountDownLatch latch = new CountDownLatch(1);
Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
+ MediaRoute2Info routeToSelect = routes.get(ROUTE_ID1);
+
addRouterCallback(new RouteCallback() {});
addManagerCallback(new MediaRouter2Manager.Callback() {
@Override
public void onTransferred(RoutingSessionInfo oldSessionInfo,
RoutingSessionInfo newSessionInfo) {
if (TextUtils.equals(mPackageName, newSessionInfo.getClientPackageName())
- && newSessionInfo.getSelectedRoutes().contains(ROUTE_ID1)) {
+ && newSessionInfo.getSelectedRoutes().contains(routeToSelect.getId())) {
latch.countDown();
}
}
@@ -294,11 +301,10 @@
assertEquals(1, mManager.getRoutingSessions(mPackageName).size());
- mManager.selectRoute(mPackageName, routes.get(ROUTE_ID1));
- latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ mManager.selectRoute(mPackageName, routeToSelect);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
List<RoutingSessionInfo> sessions = mManager.getRoutingSessions(mPackageName);
-
assertEquals(2, sessions.size());
RoutingSessionInfo sessionInfo = sessions.get(1);
@@ -309,6 +315,77 @@
assertEquals(1, mManager.getRoutingSessions(mPackageName).size());
}
+ @Test
+ public void testTransfer_unknownRoute_fail() throws Exception {
+ addRouterCallback(new RouteCallback() {});
+
+ CountDownLatch onSessionCreatedLatch = new CountDownLatch(1);
+ CountDownLatch onTransferFailedLatch = new CountDownLatch(1);
+
+ addManagerCallback(new MediaRouter2Manager.Callback() {
+ @Override
+ public void onTransferred(RoutingSessionInfo oldSessionInfo,
+ RoutingSessionInfo newSessionInfo) {
+ assertNotNull(newSessionInfo);
+ onSessionCreatedLatch.countDown();
+ }
+ @Override
+ public void onTransferFailed(RoutingSessionInfo session, MediaRoute2Info route) {
+ onTransferFailedLatch.countDown();
+ }
+ });
+
+ MediaRoute2Info unknownRoute =
+ new MediaRoute2Info.Builder(TEST_ID_UNKNOWN, TEST_NAME_UNKNOWN)
+ .addFeature(FEATURE_REMOTE_PLAYBACK)
+ .build();
+
+ mManager.transfer(mManager.getSystemRoutingSession(), unknownRoute);
+ assertFalse(onSessionCreatedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertTrue(onTransferFailedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ }
+
+ @Test
+ public void testRouterRelease_managerGetRoutingSessions() throws Exception {
+ CountDownLatch transferLatch = new CountDownLatch(1);
+ CountDownLatch releaseLatch = new CountDownLatch(1);
+
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
+ MediaRoute2Info routeToSelect = routes.get(ROUTE_ID1);
+ assertNotNull(routeToSelect);
+
+ addRouterCallback(new RouteCallback() {});
+ addManagerCallback(new MediaRouter2Manager.Callback() {
+ @Override
+ public void onTransferred(RoutingSessionInfo oldSessionInfo,
+ RoutingSessionInfo newSessionInfo) {
+ if (TextUtils.equals(mPackageName, newSessionInfo.getClientPackageName())
+ && newSessionInfo.getSelectedRoutes().contains(routeToSelect.getId())) {
+ transferLatch.countDown();
+ }
+ }
+ @Override
+ public void onSessionReleased(RoutingSessionInfo session) {
+ releaseLatch.countDown();
+ }
+ });
+
+ assertEquals(1, mManager.getRoutingSessions(mPackageName).size());
+ assertEquals(1, mRouter2.getControllers().size());
+
+ mManager.transfer(mManager.getRoutingSessions(mPackageName).get(0), routeToSelect);
+ assertTrue(transferLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ assertEquals(2, mManager.getRoutingSessions(mPackageName).size());
+ assertEquals(2, mRouter2.getControllers().size());
+ mRouter2.getControllers().get(1).release();
+
+ assertTrue(releaseLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
+ assertEquals(1, mRouter2.getControllers().size());
+ assertEquals(1, mManager.getRoutingSessions(mPackageName).size());
+ }
+
/**
* Tests select, transfer, release of routes of a provider
*/
@@ -350,6 +427,35 @@
}
@Test
+ @LargeTest
+ public void testTransfer_ignored_fails() throws Exception {
+ Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
+ addRouterCallback(new RouteCallback() {});
+
+ CountDownLatch onSessionCreatedLatch = new CountDownLatch(1);
+ CountDownLatch onFailedLatch = new CountDownLatch(1);
+
+ addManagerCallback(new MediaRouter2Manager.Callback() {
+ @Override
+ public void onTransferred(RoutingSessionInfo oldSessionInfo,
+ RoutingSessionInfo newSessionInfo) {
+ onSessionCreatedLatch.countDown();
+ }
+ @Override
+ public void onTransferFailed(RoutingSessionInfo session, MediaRoute2Info route) {
+ onFailedLatch.countDown();
+ }
+ });
+
+ List<RoutingSessionInfo> sessions = mManager.getRoutingSessions(mPackageName);
+ RoutingSessionInfo targetSession = sessions.get(sessions.size() - 1);
+ mManager.transfer(targetSession, routes.get(ROUTE_ID6_TO_BE_IGNORED));
+
+ assertFalse(onSessionCreatedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ assertTrue(onFailedLatch.await(MediaRouter2Manager.TRANSFER_TIMEOUT_MS,
+ TimeUnit.MILLISECONDS));
+ }
+ @Test
public void testSetSystemRouteVolume() throws Exception {
// ensure client
addManagerCallback(new MediaRouter2Manager.Callback());
@@ -639,8 +745,10 @@
mRouter2.registerRouteCallback(mExecutor, routeCallback,
new RouteDiscoveryPreference.Builder(routeFeatures, true).build());
try {
- addedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
- featuresLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ if (mManager.getAllRoutes().isEmpty()) {
+ addedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
+ }
+ featuresLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS);
return createRouteMap(mManager.getAvailableRoutes(mPackageName));
} finally {
mRouter2.unregisterRouteCallback(routeCallback);
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/StubMediaRoute2ProviderService.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/StubMediaRoute2ProviderService.java
index 4e398f2..4551876 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/StubMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/StubMediaRoute2ProviderService.java
@@ -53,6 +53,9 @@
public static final String ROUTE_ID5_TO_TRANSFER_TO = "route_id5_to_transfer_to";
public static final String ROUTE_NAME5 = "Sample Route 5 - Route to transfer to";
+ public static final String ROUTE_ID6_TO_BE_IGNORED = "route_id6_to_be_ignored";
+ public static final String ROUTE_NAME6 = "Sample Route 6 - Route to be ignored";
+
public static final String ROUTE_ID_SPECIAL_FEATURE = "route_special_feature";
public static final String ROUTE_NAME_SPECIAL_FEATURE = "Special Feature Route";
@@ -98,7 +101,10 @@
ROUTE_ID5_TO_TRANSFER_TO, ROUTE_NAME5)
.addFeature(FEATURE_SAMPLE)
.build();
-
+ MediaRoute2Info route6 = new MediaRoute2Info.Builder(
+ ROUTE_ID6_TO_BE_IGNORED, ROUTE_NAME6)
+ .addFeature(FEATURE_SAMPLE)
+ .build();
MediaRoute2Info routeSpecial =
new MediaRoute2Info.Builder(ROUTE_ID_SPECIAL_FEATURE, ROUTE_NAME_SPECIAL_FEATURE)
.addFeature(FEATURE_SAMPLE)
@@ -121,6 +127,7 @@
mRoutes.put(route3.getId(), route3);
mRoutes.put(route4.getId(), route4);
mRoutes.put(route5.getId(), route5);
+ mRoutes.put(route6.getId(), route6);
mRoutes.put(routeSpecial.getId(), routeSpecial);
mRoutes.put(fixedVolumeRoute.getId(), fixedVolumeRoute);
@@ -219,6 +226,10 @@
notifyRequestFailed(requestId, REASON_UNKNOWN_ERROR);
return;
}
+ // Ignores the request intentionally for testing
+ if (TextUtils.equals(ROUTE_ID6_TO_BE_IGNORED, routeId)) {
+ return;
+ }
maybeDeselectRoute(routeId);
final String sessionId = String.valueOf(mNextSessionId);
diff --git a/packages/SettingsLib/AdaptiveIcon/src/com/android/settingslib/widget/AdaptiveOutlineDrawable.java b/packages/SettingsLib/AdaptiveIcon/src/com/android/settingslib/widget/AdaptiveOutlineDrawable.java
index 4438893..3bf43dd 100644
--- a/packages/SettingsLib/AdaptiveIcon/src/com/android/settingslib/widget/AdaptiveOutlineDrawable.java
+++ b/packages/SettingsLib/AdaptiveIcon/src/com/android/settingslib/widget/AdaptiveOutlineDrawable.java
@@ -29,7 +29,12 @@
import android.graphics.Rect;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.DrawableWrapper;
+import android.os.RemoteException;
+import android.util.DisplayMetrics;
import android.util.PathParser;
+import android.view.Display;
+import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
import androidx.annotation.IntDef;
import androidx.annotation.VisibleForTesting;
@@ -56,6 +61,7 @@
private int mStrokeWidth;
private Bitmap mBitmap;
private int mType;
+ private float mDensity;
public AdaptiveOutlineDrawable(Resources resources, Bitmap bitmap) {
super(new AdaptiveIconShapeDrawable(resources));
@@ -77,6 +83,7 @@
mPath = new Path(PathParser.createPathFromPathData(
resources.getString(com.android.internal.R.string.config_icon_mask)));
mStrokeWidth = resources.getDimensionPixelSize(R.dimen.adaptive_outline_stroke);
+ mDensity = resources.getDisplayMetrics().density;
mOutlinePaint = new Paint();
mOutlinePaint.setColor(getColor(resources, type));
mOutlinePaint.setStyle(Paint.Style.STROKE);
@@ -130,7 +137,12 @@
if (mType == TYPE_DEFAULT) {
canvas.drawPath(mPath, mOutlinePaint);
} else {
- canvas.drawCircle(2 * mInsetPx, 2 * mInsetPx, 2 * mInsetPx - mStrokeWidth,
+ final float defaultDensity = getDefaultDisplayDensity(Display.DEFAULT_DISPLAY)
+ / (float) DisplayMetrics.DENSITY_DEFAULT;
+ final int insetPx =
+ Math.round(mInsetPx / (float) (Math.floor(
+ (mDensity / defaultDensity) * 100) / 100.0));
+ canvas.drawCircle(2 * insetPx, 2 * insetPx, 2 * insetPx - mStrokeWidth,
mOutlinePaint);
}
canvas.restoreToCount(count);
@@ -139,6 +151,15 @@
canvas.drawBitmap(mBitmap, bounds.left + mInsetPx, bounds.top + mInsetPx, null);
}
+ private static int getDefaultDisplayDensity(int displayId) {
+ try {
+ final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+ return wm.getInitialDisplayDensity(displayId);
+ } catch (RemoteException exc) {
+ return -1;
+ }
+ }
+
@Override
public int getIntrinsicHeight() {
return mBitmap.getHeight() + 2 * mInsetPx;
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 1d4cfdc..a89cf37 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -60,6 +60,7 @@
import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
import com.android.settingslib.Utils;
+import com.android.settingslib.utils.ThreadUtils;
import java.io.File;
import java.io.IOException;
@@ -1588,6 +1589,15 @@
this.size = SIZE_UNKNOWN;
this.sizeStale = true;
ensureLabel(context);
+ // Speed up the cache of the icon and label description if they haven't been created.
+ ThreadUtils.postOnBackgroundThread(() -> {
+ if (this.icon == null) {
+ this.ensureIconLocked(context);
+ }
+ if (this.labelDescription == null) {
+ this.ensureLabelDescriptionLocked(context);
+ }
+ });
}
public void ensureLabel(Context context) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index d1cd043..3015397 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -900,9 +900,7 @@
updateNetworkInfo(info);
fetchScansAndConfigsAndUpdateAccessPoints();
} else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
- NetworkInfo info =
- mConnectivityManager.getNetworkInfo(mWifiManager.getCurrentNetwork());
- updateNetworkInfo(info);
+ updateNetworkInfo(/* networkInfo= */ null);
}
}
};
@@ -948,7 +946,7 @@
// We don't send a NetworkInfo object along with this message, because even if we
// fetch one from ConnectivityManager, it might be older than the most recent
// NetworkInfo message we got via a WIFI_STATE_CHANGED broadcast.
- updateNetworkInfo(null);
+ updateNetworkInfo(/* networkInfo= */ null);
}
}
}
diff --git a/packages/SystemUI/res/color/qs_user_detail_avatar_tint.xml b/packages/SystemUI/res/color/qs_user_detail_avatar_tint.xml
deleted file mode 100644
index 696e9b1..0000000
--- a/packages/SystemUI/res/color/qs_user_detail_avatar_tint.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- ~ Copyright (C) 2016 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
- -->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_enabled="false" android:color="?android:attr/textColorPrimary" />
- <item android:color="@android:color/transparent" />
-</selector>
diff --git a/packages/SystemUI/res/drawable/ic_error_outline.xml b/packages/SystemUI/res/drawable/ic_error_outline.xml
new file mode 100644
index 0000000..140180a
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_error_outline.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 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
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M11,15h2v2h-2v-2zM11,7h2v6h-2L11,7zM11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_settings_power.xml b/packages/SystemUI/res/drawable/ic_settings_power.xml
new file mode 100644
index 0000000..137c289
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_settings_power.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ Copyright (C) 2020 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.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M8,24c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1 -1,0.45 -1,1 0.45,1 1,1zM12,24c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1 -1,0.45 -1,1 0.45,1 1,1zM13,2h-2v10h2L13,2zM16.56,4.44l-1.45,1.45C16.84,6.94 18,8.83 18,11c0,3.31 -2.69,6 -6,6s-6,-2.69 -6,-6c0,-2.17 1.16,-4.06 2.88,-5.12L7.44,4.44C5.36,5.88 4,8.28 4,11c0,4.42 3.58,8 8,8s8,-3.58 8,-8c0,-2.72 -1.36,-5.12 -3.44,-6.56zM16,24c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1 -1,0.45 -1,1 0.45,1 1,1z"
+ android:fillColor="#000000"/>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout-sw600dp/keyguard_user_switcher_item.xml b/packages/SystemUI/res/layout-sw600dp/keyguard_user_switcher_item.xml
index 4413b1e..9ce030e 100644
--- a/packages/SystemUI/res/layout-sw600dp/keyguard_user_switcher_item.xml
+++ b/packages/SystemUI/res/layout-sw600dp/keyguard_user_switcher_item.xml
@@ -27,13 +27,13 @@
android:gravity="end|center_vertical"
android:clickable="true"
android:background="@drawable/kg_user_switcher_rounded_bg"
+ sysui:activatedTextAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher"
sysui:regularTextAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher">
<TextView android:id="@+id/user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="25dp"
android:layout_marginEnd="12dp"
- android:textAppearance="@style/TextAppearance.StatusBar.Expanded.UserSwitcher"
/>
<com.android.systemui.statusbar.phone.UserAvatarView android:id="@+id/user_picture"
android:layout_width="@dimen/kg_framed_avatar_size"
diff --git a/packages/SystemUI/res/layout/controls_base_item.xml b/packages/SystemUI/res/layout/controls_base_item.xml
index 477a70f..5f83f45 100644
--- a/packages/SystemUI/res/layout/controls_base_item.xml
+++ b/packages/SystemUI/res/layout/controls_base_item.xml
@@ -52,6 +52,7 @@
android:singleLine="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit = "marquee_forever"
+ android:textDirection="locale"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="@+id/icon"
app:layout_constraintStart_toEndOf="@+id/icon" />
@@ -67,6 +68,7 @@
android:focusable="false"
android:maxLines="1"
android:ellipsize="end"
+ android:textDirection="locale"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/barrier"/>
@@ -90,6 +92,7 @@
android:focusable="false"
android:maxLines="1"
android:ellipsize="end"
+ android:textDirection="locale"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/favorite"
app:layout_constraintTop_toTopOf="@id/favorite"
diff --git a/packages/SystemUI/res/layout/controls_more_item.xml b/packages/SystemUI/res/layout/controls_more_item.xml
index df03787..da9c43c 100644
--- a/packages/SystemUI/res/layout/controls_more_item.xml
+++ b/packages/SystemUI/res/layout/controls_more_item.xml
@@ -20,5 +20,6 @@
android:layout_height="wrap_content"
android:layout_gravity="start"
android:paddingStart="@dimen/control_menu_horizontal_padding"
- android:paddingEnd="@dimen/control_menu_horizontal_padding"/>
+ android:paddingEnd="@dimen/control_menu_horizontal_padding"
+ android:textDirection="locale"/>
diff --git a/packages/SystemUI/res/layout/global_screenshot_static.xml b/packages/SystemUI/res/layout/global_screenshot_static.xml
index a46823d..da5277c 100644
--- a/packages/SystemUI/res/layout/global_screenshot_static.xml
+++ b/packages/SystemUI/res/layout/global_screenshot_static.xml
@@ -53,15 +53,6 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</HorizontalScrollView>
- <ImageView
- android:id="@+id/global_screenshot_animated_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_gravity="center"
- android:visibility="gone"
- android:elevation="@dimen/screenshot_preview_elevation"
- android:background="@drawable/screenshot_rounded_corners"
- android:adjustViewBounds="true"/>
<include layout="@layout/global_screenshot_preview"/>
<FrameLayout
android:id="@+id/global_screenshot_dismiss_button"
diff --git a/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml b/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
index 626951c..1cd1a04 100644
--- a/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
+++ b/packages/SystemUI/res/layout/keyguard_user_switcher_item.xml
@@ -39,8 +39,6 @@
android:layout_width="@dimen/kg_framed_avatar_size"
android:layout_height="@dimen/kg_framed_avatar_size"
android:contentDescription="@null"
- android:backgroundTint="@color/qs_user_detail_avatar_tint"
- android:backgroundTintMode="src_atop"
sysui:frameWidth="@dimen/keyguard_user_switcher_border_thickness"
sysui:framePadding="2.5dp"
sysui:badgeDiameter="18dp"
diff --git a/packages/SystemUI/res/layout/partial_conversation_info.xml b/packages/SystemUI/res/layout/partial_conversation_info.xml
index 803b0c6..ecc3118 100644
--- a/packages/SystemUI/res/layout/partial_conversation_info.xml
+++ b/packages/SystemUI/res/layout/partial_conversation_info.xml
@@ -35,7 +35,7 @@
android:clipChildren="false"
android:clipToPadding="false">
<ImageView
- android:id="@+id/conversation_icon"
+ android:id="@+id/icon"
android:layout_width="@dimen/notification_guts_conversation_icon_size"
android:layout_height="@dimen/notification_guts_conversation_icon_size"
android:layout_centerVertical="true"
@@ -60,20 +60,6 @@
android:textDirection="locale"
style="@style/TextAppearance.NotificationImportanceChannel"/>
<TextView
- android:id="@+id/parent_channel_name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:ellipsize="end"
- android:textDirection="locale"
- style="@style/TextAppearance.NotificationImportanceChannel"/>
- <TextView
- android:id="@+id/group_name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:ellipsize="end"
- android:textDirection="locale"
- style="@style/TextAppearance.NotificationImportanceChannelGroup"/>
- <TextView
android:id="@+id/delegate_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml
index 0608685..cc6c5d3 100644
--- a/packages/SystemUI/res/layout/qs_user_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml
@@ -30,6 +30,7 @@
android:clipToPadding="false"
android:focusable="true"
android:background="@drawable/ripple_drawable"
+ systemui:activatedTextAppearance="@style/TextAppearance.QS.UserSwitcher"
systemui:regularTextAppearance="@style/TextAppearance.QS.UserSwitcher">
<com.android.systemui.statusbar.phone.UserAvatarView
@@ -37,8 +38,6 @@
android:layout_width="@dimen/qs_framed_avatar_size"
android:layout_height="@dimen/qs_framed_avatar_size"
android:layout_marginBottom="7dp"
- android:backgroundTint="@color/qs_user_detail_avatar_tint"
- android:backgroundTintMode="src_atop"
systemui:frameWidth="6dp"
systemui:badgeDiameter="18dp"
systemui:badgeMargin="1dp"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 45d4cb4..88102b2 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Beweeg na regs bo"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Beweeg na links onder"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Beweeg na regs onder"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Maak toe"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Moenie dat gesprek \'n borrel word nie"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Klets met borrels"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Nuwe gesprekke verskyn as swerwende ikone, of borrels Tik op borrel om dit oop te maak. Sleep om dit te skuif."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Swiep om meer te sien"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Laai tans aanbevelings"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Maak hierdie mediasessie toe"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Hervat"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Onaktief, gaan program na"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Fout, probeer tans weer …"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Toestel is verwyder"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Nie gekry nie"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrole is nie beskikbaar nie"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Kon nie by <xliff:g id="DEVICE">%1$s</xliff:g> ingaan nie. Gaan die <xliff:g id="APPLICATION">%2$s</xliff:g>-program na om seker te maak dat die kontrole steeds beskikbaar is en dat die programinstellings nie verander het nie."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Maak program oop"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Kan nie status laai nie"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Fout, probeer weer"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Besig"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index a88be36..66c0131 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"ወደ ላይኛው ቀኝ አንቀሳቅስ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"የግርጌውን ግራ አንቀሳቅስ"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"ታችኛውን ቀኝ ያንቀሳቅሱ"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"አሰናብት"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"ውይይቶችን በአረፋ አታሳይ"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"አረፋዎችን በመጠቀም ይወያዩ"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"አዲስ ውይይቶች እንደ ተንሳፋፊ አዶዎች ወይም አረፋዎች ሆነው ይታያሉ። አረፋን ለመክፈት መታ ያድርጉ። ለመውሰድ ይጎትቱት።"</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"ተጨማሪ ለማየት ያንሸራትቱ"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ምክሮችን በመጫን ላይ"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"ይህን የሚዲያ ክፍለ-ጊዜ ዝጋ"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"ከቆመበት ቀጥል"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ንቁ ያልኾነ፣ መተግበሪያን ይፈትሹ"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"ስህተት፣ እንደገና በመሞከር ላይ…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"መሣሪያ ተወግዷል"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"አልተገኘም"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"መቆጣጠሪያ አይገኝም"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g>ን መድረስ አልተቻለም። አሁንም ድረስ መቆጣጠሪያው ሊገኝ እንደሚችል እና የመተግበሪያ ቅንብሮቹ እንዳልተለወጡ ለማረጋገጥ <xliff:g id="APPLICATION">%2$s</xliff:g> መተግበሪያን ይፈትሹ።"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"መተግበሪያ ክፈት"</string>
<string name="controls_error_generic" msgid="352500456918362905">"ሁኔታን መጫን አልተቻልም"</string>
<string name="controls_error_failed" msgid="960228639198558525">"ስህተት፣ እንደገና ይሞክሩ"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"በሂደት ላይ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 2a0af5d..ebf4bc8 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -1022,7 +1022,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"الانتقال إلى أعلى اليسار"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"نقل إلى أسفل يمين الشاشة"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"نقل إلى أسفل اليسار"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"تجاهل"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"عدم عرض المحادثة كفقاعة محادثة"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"الدردشة باستخدام فقاعات المحادثات"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"تظهر المحادثات الجديدة كرموز عائمة أو كفقاعات. انقر لفتح فقاعة المحادثة، واسحبها لتحريكها."</string>
@@ -1086,9 +1087,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"مرّر سريعًا لرؤية المزيد."</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"جارٍ تحميل الاقتراحات"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"إغلاق جلسة تشغيل الوسائط هذه"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"استئناف التشغيل"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"غير نشط، تحقّق من التطبيق."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"حدث خطأ، جارٍ إعادة المحاولة…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"تمت إزالة الجهاز."</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"لم يتم العثور عليه."</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"عنصر التحكّم غير متوفّر"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"تعذّر الوصول إلى <xliff:g id="DEVICE">%1$s</xliff:g>. تحقّق من تطبيق <xliff:g id="APPLICATION">%2$s</xliff:g> للتأكّد من أن عنصر التحكّم لا يزال متوفّرًا وأنه لم يتم تغيير إعدادات التطبيق."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"فتح التطبيق"</string>
<string name="controls_error_generic" msgid="352500456918362905">"يتعذّر تحميل الحالة."</string>
<string name="controls_error_failed" msgid="960228639198558525">"حدث خطأ، يُرجى إعادة المحاولة."</string>
<string name="controls_in_progress" msgid="4421080500238215939">"قيد التقدم"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index e3fd2cb..c3d1e78 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"শীৰ্ষৰ সোঁফালে নিয়ক"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"বুটামটো বাওঁফালে নিয়ক"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"তলৰ সোঁফালে নিয়ক"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"অগ্ৰাহ্য কৰক"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"বাৰ্তালাপ বাবল নকৰিব"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Bubbles ব্যৱহাৰ কৰি চাট কৰক"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"নতুন বাৰ্তালাপ উপঙি থকা চিহ্নসমূহ অথবা bubbles হিচাপে প্ৰদর্শিত হয়। Bubbles খুলিবলৈ টিপক। এইটো স্থানান্তৰ কৰিবলৈ টানি নিয়ক।"</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"অধিক চাবলৈ ছোৱাইপ কৰক"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"চুপাৰিছসমূহ ল’ড কৰি থকা হৈছে"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"এই মিডিয়া ছেশ্বনটো বন্ধ কৰক"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"পুনৰ আৰম্ভ কৰক"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"সক্ৰিয় নহয়, এপ্টো পৰীক্ষা কৰক"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"আসোঁৱাহ, পুনৰ চেষ্টা কৰি আছে…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"ডিভাইচটো আঁতৰোৱা হৈছে"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"বিচাৰি পোৱা নগ’ল"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"নিয়ন্ত্ৰণটো উপলব্ধ নহয়"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> এক্সেছ কৰিব পৰা নগ’ল। নিয়ন্ত্ৰণটো এতিয়াও উপলব্ধ আৰু এপ্টোৰ ছেটিংসমূহ সলনি কৰা হোৱা নাই বুলি নিশ্চিত কৰিবলৈ <xliff:g id="APPLICATION">%2$s</xliff:g> এপ্টো পৰীক্ষা কৰক।"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"এপ্টো খোলক"</string>
<string name="controls_error_generic" msgid="352500456918362905">"স্থিতি ল’ড কৰিব নোৱাৰি"</string>
<string name="controls_error_failed" msgid="960228639198558525">"আসোঁৱাহ হৈছে, আকৌ চেষ্টা কৰক"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"চলি আছে"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 0adee8c..3919fe3 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Yuxarıya sağa köçürün"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Aşağıya sola köçürün"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Aşağıya sağa köçürün"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Kənarlaşdırın"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Söhbətdən gələn bildirişi göstərməyin"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Yumrucuqlardan istifadə edərək söhbət edin"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Yeni söhbətlər üzən nişanlar və ya yumrucuqlar kimi görünür. Yumrucuğu açmaq üçün toxunun. Hərəkət etdirmək üçün sürüşdürün."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Digərlərini görmək üçün sürüşdürün"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Tövsiyələr yüklənir"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Bu media sessiyasını bağlayın"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Davam edin"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Aktiv deyil, tətbiqi yoxlayın"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Xəta, yenidən cəhd edilir…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Cihaz silindi"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Tapılmadı"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Nəzarət əlçatan deyil"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> cihazına giriş mümkün olmadı. <xliff:g id="APPLICATION">%2$s</xliff:g> tətbiqini yoxlayaraq nəzarətin hələ də əlçatan olduğuna və tətbiq ayarlarının dəyişmədiyinə əmin olun."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Tətbiqi açın"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Statusu yükləmək alınmadı"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Xəta, yenidən cəhd edin"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Davam edir"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 868d1cb..f2a6d65 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -1007,9 +1007,10 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Premesti gore desno"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Premesti dole levo"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Premesti dole desno"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Odbaci"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Ne koristi oblačiće za konverzaciju"</string>
- <string name="bubbles_user_education_title" msgid="5547017089271445797">"Ćaskajte pomoću oblačića"</string>
+ <string name="bubbles_user_education_title" msgid="5547017089271445797">"Ćaskajte u oblačićima"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Nove konverzacije se prikazuju kao plutajuće ikone ili oblačići. Dodirnite da biste otvorili oblačić. Prevucite da biste ga premestili."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Kontrolišite oblačiće u bilo kom trenutku"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Dodirnite Upravljajte da biste isključili oblačiće iz ove aplikacije"</string>
@@ -1068,9 +1069,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Prevucite da biste videli još"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavaju se preporuke"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Zatvorite ovu sesiju medija"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno. Vidite aplikaciju"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Greška, pokušava se ponovo…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Uređaj je uklonjen"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrola nije dostupna"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Pristupanje uređaju <xliff:g id="DEVICE">%1$s</xliff:g> nije uspelo. Pogledajte aplikaciju <xliff:g id="APPLICATION">%2$s</xliff:g> da biste se uverili da je kontrola još uvek dostupna i da se podešavanja aplikacije nisu promenila."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Otvori aplikaciju"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Učitavanje statusa nije uspelo"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Greška. Probajte ponovo"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"U toku"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 04cd56a..d34f089 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -1012,9 +1012,10 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Перамясціце правей і вышэй"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Перамясціць лявей і ніжэй"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Перамясціць правей і ніжэй"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Адхіліць"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Не паказваць размову ў выглядзе ўсплывальных апавяшчэнняў"</string>
- <string name="bubbles_user_education_title" msgid="5547017089271445797">"Размаўляйце ў чаце, які паказвае ўсплывальныя апавяшчэнні"</string>
+ <string name="bubbles_user_education_title" msgid="5547017089271445797">"Усплывальныя апавяшчэнні"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Новыя размовы будуць паказвацца як рухомыя значкі ці ўсплывальныя апавяшчэнні. Націсніце, каб адкрыць усплывальнае апавяшчэнне. Перацягніце яго, каб перамясціць."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Кіруйце ўсплывальнымі апавяшчэннямі ў любы час"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Каб выключыць усплывальныя апавяшчэнні з гэтай праграмы, націсніце \"Кіраваць\""</string>
@@ -1074,9 +1075,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Правядзіце пальцам, каб убачыць больш інфармацыі"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Загружаюцца рэкамендацыі"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Закрыць гэты сеанс мультымедыя"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Узнавіць"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактыўна, праверце праграму"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Памылка, паўторная спроба…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Прылада выдалена"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Не знойдзена"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Кіраванне недаступнае"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Не ўдалося атрымаць доступ да прылады \"<xliff:g id="DEVICE">%1$s</xliff:g>\". Праверце, ці не змяніліся налады праграмы \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" і ці даступная ў ёй функцыя кіравання."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Адкрыць праграму"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Не ўдалося загрузіць стан"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Памылка, паўтарыце спробу"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Выконваецца"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 034217c..2388cf6 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Преместване горе вдясно"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Преместване долу вляво"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Преместване долу вдясно"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Отхвърляне"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Без балончета за разговора"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Разговаряне чрез балончета"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Новите разговори се показват като плаващи икони, или балончета. Докоснете балонче, за да го отворите, или го плъзнете, за да го преместите."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Прекарайте пръст, за да видите повече"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Препоръките се зареждат"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Затваряне на тази сесия за мултимедия"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Възобновяване"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, проверете прилож."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Грешка. Извършва се нов опит…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Устройството бе премахнато"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Не е намерено"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Контролата не е налице"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Няма достъп до <xliff:g id="DEVICE">%1$s</xliff:g>. Отворете приложението <xliff:g id="APPLICATION">%2$s</xliff:g> и проверете дали контролата още е налице и дали настройките му не са променени."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Към приложението"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Състоян. не може да се зареди"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Грешка. Опитайте отново"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"В ход"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 7482dfe..d5e827f 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"উপরে ডানদিকে সরান"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"নিচে বাঁদিকে সরান"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"নিচে ডান দিকে সরান"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"খারিজ করুন"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"কথোপকথন বাবল হিসেবে দেখাবে না"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"বাবল ব্যবহার করে চ্যাট করুন"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"নতুন কথোপকথন ভেসে থাকা আইকন বা বাবল হিসেবে দেখানো হয়। বাবল খুলতে ট্যাপ করুন। সেটি সরাতে ধরে টেনে আনুন।"</string>
@@ -1013,17 +1014,14 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"সিস্টেম নেভিগেশন আপডেট হয়েছে। পরিবর্তন করার জন্য সেটিংসে যান।"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"সিস্টেম নেভিগেশন আপডেট করতে সেটিংসে যান"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"স্ট্যান্ডবাই"</string>
- <!-- no translation found for priority_onboarding_title (2893070698479227616) -->
- <skip />
- <!-- no translation found for priority_onboarding_behavior (5342816047020432929) -->
- <skip />
+ <string name="priority_onboarding_title" msgid="2893070698479227616">"কথোপকথনকে \'গুরুত্বপূর্ণ\' হিসেবে সেট করা হয়েছে"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"গুরুত্বপূর্ণ কথোপকথন:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"কথোপকথনের বিভাগের উপরে দেখান"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"লক স্ক্রিনে প্রোফাইল ছবি দেখান"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"অ্যাপের উপরে একটি ভাসমান বুদবুদ হিসেবে দেখা যাবে"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"বিরক্ত করবে না মোডে ব্যাঘাত ঘটাতে পারে"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"বুঝেছি"</string>
- <!-- no translation found for priority_onboarding_settings_button_title (6663601574303585927) -->
- <skip />
+ <string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"সেটিংস"</string>
<string name="magnification_overlay_title" msgid="6584179429612427958">"ওভারলে উইন্ডো বড় করে দেখা"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"উইন্ডো বড় করে দেখা"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"উইন্ডো কন্ট্রোল বড় করে দেখা"</string>
@@ -1065,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"আরও দেখতে সোয়াইপ করুন"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"সাজেশন লোড করা হচ্ছে"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"এই মিডিয়া সেশন বেছে নিন"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"আবার চালু করুন"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"বন্ধ আছে, অ্যাপ চেক করুন"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"সমস্যা, আবার চেষ্টা করা হচ্ছে…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"ডিভাইস সরিয়ে দেওয়া হয়েছে"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"খুঁজে পাওয়া যায়নি"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"কন্ট্রোল উপলভ্য নেই"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> ডিভাইস অ্যাক্সেস করা যায়নি। <xliff:g id="APPLICATION">%2$s</xliff:g> অ্যাপ চেক করে দেখুন যাতে এটি নিশ্চিত করে নিতে পারেন যে কন্ট্রোল এখনও উপলভ্য আছে এবং অ্যাপ সেটিংসে কোনও পরিবর্তন করা হয়নি।"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"অ্যাপ খুলুন"</string>
<string name="controls_error_generic" msgid="352500456918362905">"স্ট্যাটাস লোড করা যাচ্ছে না"</string>
<string name="controls_error_failed" msgid="960228639198558525">"সমস্যা হয়েছে, আবার চেষ্টা করুন"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"চলছে"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index c049c5f..37397f9 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -92,13 +92,13 @@
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Obrađivanje snimka ekrana"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Obavještenje za sesiju snimanja ekrana je u toku"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Započeti snimanje?"</string>
- <string name="screenrecord_description" msgid="1123231719680353736">"Prilikom snimanja, sistem Android može snimiti sve osjetljive informacije koje su vidljive na vašem ekranu ili koje reproducirate na uređaju. To uključuje lozinke, informacije za plaćanje, fotografije, poruke i zvuk."</string>
+ <string name="screenrecord_description" msgid="1123231719680353736">"Prilikom snimanja, Android sistem može snimiti sve osjetljive informacije koje su vidljive na vašem ekranu ili koje reproducirate na uređaju. To uključuje lozinke, informacije za plaćanje, fotografije, poruke i zvuk."</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Snimi zvučni zapis"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Zvuk uređaja"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Zvuk s vašeg uređaja, naprimjer muzika, pozivi i melodije zvona"</string>
<string name="screenrecord_mic_label" msgid="2111264835791332350">"Mikrofon"</string>
<string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Zvuk i mikrofon uređaja"</string>
- <string name="screenrecord_start" msgid="330991441575775004">"Počni"</string>
+ <string name="screenrecord_start" msgid="330991441575775004">"Započni"</string>
<string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Snimanje ekrana"</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Snimanje ekrana i zvuka"</string>
<string name="screenrecord_taps_label" msgid="1595690528298857649">"Prikaži dodire na ekranu"</string>
@@ -1009,7 +1009,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Pomjerite gore desno"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Pomjeri dolje lijevo"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Pomjerite dolje desno"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Odbaci"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nemoj prikazivati razgovor u oblačićima"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chatajte koristeći oblačiće"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Novi razgovori se prikazuju kao plutajuće ikone ili oblačići. Dodirnite da otvorite oblačić. Prevucite da ga premjestite."</string>
@@ -1070,9 +1071,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Prevucite da vidite više"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavanje preporuka"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Zatvori ovu medijsku sesiju"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, vidite aplikaciju"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Greška, ponovni pokušaj…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Uređaj je uklonjen"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrola nije dostupna"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Pristup uređaju <xliff:g id="DEVICE">%1$s</xliff:g> nije uspio. Provjerite aplikaciju <xliff:g id="APPLICATION">%2$s</xliff:g> da se uvjerite da je kontrola i dalje dostupna i da se postavke aplikacije nisu promijenile."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Otvori aplikaciju"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Nije moguće učitati status"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Greška, pokušajte ponovo"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"U toku"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 506429c..2fdddf71 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Mou a dalt a la dreta"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Mou a baix a l\'esquerra"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Mou a baix a la dreta"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Omet"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"No mostris la conversa com a bombolla"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Xateja utilitzant les bombolles"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Les converses noves es mostren com a icones flotants o bombolles. Toca per obrir una bombolla. Arrossega-la per moure-la."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Llisca per veure\'n més"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregant les recomanacions"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Tanca aquesta sessió multimèdia"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Reprèn"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactiu; comprova l\'aplicació"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error. S\'està tornant a provar…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"El dispositiu s\'ha suprimit"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"No s\'ha trobat"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"El control no està disponible"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"No s\'ha pogut accedir a <xliff:g id="DEVICE">%1$s</xliff:g>. Consulta l\'aplicació <xliff:g id="APPLICATION">%2$s</xliff:g> per assegurar-te que el control encara estigui disponible i que la configuració de l\'aplicació no hagi canviat."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Obre l\'aplicació"</string>
<string name="controls_error_generic" msgid="352500456918362905">"No es pot carregar l\'estat"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Error; torna-ho a provar"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"En curs"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 48ab79e..18012b5 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -1012,7 +1012,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Přesunout vpravo nahoru"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Přesunout vlevo dolů"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Přesunout vpravo dolů"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Zavřít"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nezobrazovat konverzaci v bublinách"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chatujte pomocí bublin"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Nové konverzace se zobrazují jako plovoucí ikony, neboli bubliny. Klepnutím bublinu otevřete. Přetažením ji posunete."</string>
@@ -1074,9 +1075,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Přejetím prstem zobrazíte další položky"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Načítání doporučení"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Zavřít tuto mediální relaci"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Pokračovat"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivní, zkontrolujte aplikaci"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Chyba. Nový pokus…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Zařízení bylo odebráno"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Nenalezeno"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Ovládání není k dispozici"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Zařízení <xliff:g id="DEVICE">%1$s</xliff:g> nelze použít. V aplikaci <xliff:g id="APPLICATION">%2$s</xliff:g> zkontrolujte, zda je ovládání stále k dispozici a zda se nezměnilo nastavení."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Otevřít aplikaci"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Stav nelze načíst"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Chyba, zkuste to znovu"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Probíhá"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 8d2d5c5..3f71e3d 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Flyt op til højre"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Flyt ned til venstre"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Flyt ned til højre"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Afvis"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Vis ikke samtaler i bobler"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chat ved hjælp af bobler"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Nye samtaler vises som svævende ikoner eller bobler. Tryk for at åbne boblen. Træk for at flytte den."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Stryg for at se mere"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Indlæser anbefalinger"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Luk denne mediesession"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Genoptag"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Tjek appen"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Fejl. Prøver igen…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Enheden er fjernet"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Ikke fundet"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Styringselement ikke tilgængeligt"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Der kunne ikke skaffes adgang til <xliff:g id="DEVICE">%1$s</xliff:g>. Tjek <xliff:g id="APPLICATION">%2$s</xliff:g>-appen for at sikre at styringselementet stadig er tilgængeligt, og at appens indstillinger ikke er blevet ændret."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Åbn app"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Statussen kan ikke indlæses"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Der opstod en fejl. Prøv igen"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"I gang"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 50cb3f3..075a496 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Nach rechts oben verschieben"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Nach unten links verschieben"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Nach unten rechts verschieben"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Schließen"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Unterhaltung nicht als Bubble anzeigen"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Bubbles zum Chatten verwenden"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Neue Unterhaltungen erscheinen als unverankerte Symbole, \"Bubbles\" genannt. Wenn du die Bubble öffnen möchtest, tippe sie an. Wenn du sie verschieben möchtest, zieh an ihr."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Wischen, um weitere zu sehen"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Empfehlungen werden geladen"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Diese Mediensitzung schließen"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Fortsetzen"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv – sieh in der App nach"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Fehler. Neuer Versuch…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Gerät entfernt"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Nicht gefunden"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Steuerelement nicht verfügbar"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Zugriff auf <xliff:g id="DEVICE">%1$s</xliff:g> nicht möglich. Prüfe, ob das Steuerelement in der App \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" noch verfügbar ist und die App-Einstellungen nicht geändert wurden."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"App öffnen"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Status kann nicht geladen werden"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Fehler – versuch es noch mal"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Läuft"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 6a32d57..c8db318 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Μετακίνηση επάνω δεξιά"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Μετακίνηση κάτω αριστερά"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Μετακίνηση κάτω δεξιά"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Παράβλεψη"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Να μην γίνει προβολή της συζήτησης σε συννεφάκια."</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Συζητήστε χρησιμοποιώντας συννεφάκια."</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Οι νέες συζητήσεις εμφανίζονται ως κινούμενα εικονίδια ή φούσκες. Πατήστε για να ανοίξετε τη φούσκα. Σύρετε για να το μετακινήσετε."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Σύρετε για να δείτε περισσότερα."</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Φόρτωση προτάσεων"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Κλείσιμο αυτής της περιόδου λειτουργίας μέσων."</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Συνέχιση"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Ανενεργό, έλεγχος εφαρμογής"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Προέκυψε σφάλμα. Επανάληψη…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Η συσκευή καταργήθηκε"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Δεν βρέθηκε."</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Μη διαθέσιμο στοιχείο ελέγχου"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Δεν ήταν δυνατή η πρόσβαση στη συσκευή <xliff:g id="DEVICE">%1$s</xliff:g>. Ελέγξτε την εφαρμογή <xliff:g id="APPLICATION">%2$s</xliff:g> για να βεβαιωθείτε ότι το στοιχείο ελέγχου εξακολουθεί να είναι διαθέσιμο και ότι οι ρυθμίσεις της εφαρμογής δεν έχουν αλλάξει."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Άνοιγμα εφαρμογής"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Αδυναμία φόρτωσης κατάστασης"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Σφάλμα, προσπαθήστε ξανά."</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Σε εξέλιξη"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 35f09af..708f2f4 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Move top right"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Move bottom left"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Move bottom right"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Dismiss"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Don’t bubble conversation"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chat using bubbles"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe to see more"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Close this media session"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, retrying…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Device removed"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Control is unavailable"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Couldn’t access <xliff:g id="DEVICE">%1$s</xliff:g>. Check the <xliff:g id="APPLICATION">%2$s</xliff:g> app to make sure that the control is still available and that the app settings haven’t changed."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Open app"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Can’t load status"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Error, try again"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"In progress"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 8c8db6a..313c604 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Move top right"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Move bottom left"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Move bottom right"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Dismiss"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Don’t bubble conversation"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chat using bubbles"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe to see more"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Close this media session"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, retrying…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Device removed"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Control is unavailable"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Couldn’t access <xliff:g id="DEVICE">%1$s</xliff:g>. Check the <xliff:g id="APPLICATION">%2$s</xliff:g> app to make sure that the control is still available and that the app settings haven’t changed."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Open app"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Can’t load status"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Error, try again"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"In progress"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 35f09af..708f2f4 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Move top right"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Move bottom left"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Move bottom right"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Dismiss"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Don’t bubble conversation"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chat using bubbles"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe to see more"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Close this media session"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, retrying…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Device removed"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Control is unavailable"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Couldn’t access <xliff:g id="DEVICE">%1$s</xliff:g>. Check the <xliff:g id="APPLICATION">%2$s</xliff:g> app to make sure that the control is still available and that the app settings haven’t changed."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Open app"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Can’t load status"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Error, try again"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"In progress"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 35f09af..708f2f4 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Move top right"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Move bottom left"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Move bottom right"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Dismiss"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Don’t bubble conversation"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chat using bubbles"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe to see more"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Close this media session"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, retrying…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Device removed"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Control is unavailable"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Couldn’t access <xliff:g id="DEVICE">%1$s</xliff:g>. Check the <xliff:g id="APPLICATION">%2$s</xliff:g> app to make sure that the control is still available and that the app settings haven’t changed."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Open app"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Can’t load status"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Error, try again"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"In progress"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index e514ccb..5d2e3eb 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -1002,7 +1002,7 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Move top right"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Move bottom left"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Move bottom right"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Dismiss"</string>
+ <string name="bubble_dismiss_text" msgid="1314082410868930066">"Dismiss bubble"</string>
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Don’t bubble conversation"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chat using bubbles"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"New conversations appear as floating icons, or bubbles. Tap to open bubble. Drag to move it."</string>
@@ -1062,10 +1062,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe to see more"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Loading recommendations"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Close this media session"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Resume"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactive, check app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, retrying…"</string>
- <!-- no translation found for controls_error_removed (6299213591234723805) -->
- <skip />
+ <string name="controls_error_removed" msgid="6675638069846014366">"Not found"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Control is unavailable"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Couldn’t access <xliff:g id="DEVICE">%1$s</xliff:g>. Check the <xliff:g id="APPLICATION">%2$s</xliff:g> app to make sure the control is still available and that the app settings haven’t changed."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Open app"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Can’t load status"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Error, try again"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"In progress"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index b1a7427..db5b68c 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Ubicar arriba a la derecha"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Ubicar abajo a la izquierda"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Ubicar abajo a la derecha"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Ignorar"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"No mostrar la conversación en burbujas"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chat con burbujas"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Las conversaciones nuevas aparecen como elementos flotantes o burbujas. Presiona para abrir la burbuja. Arrástrala para moverla."</string>
@@ -1013,17 +1014,14 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"Se actualizó el sistema de navegación. Para hacer cambios, ve a Configuración."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"Ve a Configuración para actualizar la navegación del sistema"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"En espera"</string>
- <!-- no translation found for priority_onboarding_title (2893070698479227616) -->
- <skip />
- <!-- no translation found for priority_onboarding_behavior (5342816047020432929) -->
- <skip />
+ <string name="priority_onboarding_title" msgid="2893070698479227616">"Se estableció la conversación como prioritaria"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"Las conversaciones prioritarias harán lo siguiente:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Se muestran en la parte superior de conversaciones"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Muestran una foto de perfil en pantalla de bloqueo"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Aparecen como burbujas flotantes encima de apps"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Suspender No interrumpir"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Entendido"</string>
- <!-- no translation found for priority_onboarding_settings_button_title (6663601574303585927) -->
- <skip />
+ <string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"Configuración"</string>
<string name="magnification_overlay_title" msgid="6584179429612427958">"Ventana superpuesta de ampliación"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"Ventana de ampliación"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"Controles de ampliación de la ventana"</string>
@@ -1065,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Desliza el dedo para ver más elementos"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendaciones"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Cerrar esta sesión multimedia"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Verifica la app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Hubo un error. Reintentando…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Se quitó el dispositivo"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"No se encontró"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"El control no está disponible."</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"No se pudo acceder a <xliff:g id="DEVICE">%1$s</xliff:g>. Revisa la app de <xliff:g id="APPLICATION">%2$s</xliff:g> para asegurarte de que el control siga estando disponible y de que no haya cambiado la configuración de la app."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Abrir app"</string>
<string name="controls_error_generic" msgid="352500456918362905">"No se pudo cargar el estado"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Error. Vuelve a intentarlo."</string>
<string name="controls_in_progress" msgid="4421080500238215939">"En curso"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index f210fbb..1d8549a 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -448,7 +448,7 @@
<string name="zen_alarms_introduction" msgid="3987266042682300470">"No te molestarán los sonidos ni las vibraciones, excepto las alarmas. Seguirás escuchando el contenido que quieras reproducir, como música, vídeos y juegos."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalizar"</string>
<string name="zen_silence_introduction_voice" msgid="853573681302712348">"Esta opción bloqueará TODOS los sonidos y todas las vibraciones, por ejemplo, los vídeos, los juegos, las alarmas y la música. Seguirás pudiendo hacer llamadas."</string>
- <string name="zen_silence_introduction" msgid="6117517737057344014">"Este modo permite bloquear TODOS los sonidos y todas las vibraciones (p. ej., los de alarmas, música, vídeos y juegos)."</string>
+ <string name="zen_silence_introduction" msgid="6117517737057344014">"Este modo bloquea TODOS los sonidos y todas las vibraciones, lo que incluye alarmas, música, vídeos y juegos."</string>
<string name="keyguard_more_overflow_text" msgid="5819512373606638727">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="7248696377626341060">"Notificaciones menos urgente abajo"</string>
<string name="notification_tap_again" msgid="4477318164947497249">"Toca de nuevo para abrir"</string>
@@ -1002,10 +1002,11 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Mover arriba a la derecha"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Mover abajo a la izquierda."</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Mover abajo a la derecha"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Cerrar"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"No mostrar conversación en burbujas"</string>
- <string name="bubbles_user_education_title" msgid="5547017089271445797">"Chatear mediante burbujas"</string>
- <string name="bubbles_user_education_description" msgid="1160281719576715211">"Las conversaciones nuevas aparecen como iconos flotantes o burbujas. Toca para abrir la burbuja. Arrastra para moverla."</string>
+ <string name="bubbles_user_education_title" msgid="5547017089271445797">"Chatea con burbujas"</string>
+ <string name="bubbles_user_education_description" msgid="1160281719576715211">"Las conversaciones nuevas aparecen como iconos flotantes llamadas \"burbujas\". Toca para abrir la burbuja. Arrastra para moverla."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Controla las burbujas en cualquier momento"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Toca Gestionar para desactivar las burbujas de esta aplicación"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"Entendido"</string>
@@ -1016,7 +1017,7 @@
<string name="priority_onboarding_title" msgid="2893070698479227616">"Conversación marcada como prioritaria"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Las conversaciones prioritarias:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Se muestran en la parte superior de la sección de conversaciones"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Muestran tu imagen de perfil en la pantalla de bloqueo"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Muestran la imagen de perfil en la pantalla de bloqueo"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Aparecen como burbuja sobre las aplicaciones"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Interrumpen el modo No molestar"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"Entendido"</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Desliza el dedo para ver más"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendaciones"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Cerrar esta sesión multimedia"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Reanudar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo, comprobar aplicación"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error; reintentando…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Dispositivo quitado"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"No se ha encontrado"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"El control no está disponible"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"No se ha podido acceder a <xliff:g id="DEVICE">%1$s</xliff:g>. Comprueba que el control siga disponible en la aplicación <xliff:g id="APPLICATION">%2$s</xliff:g> y que no se haya modificado su configuración."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Abrir aplicación"</string>
<string name="controls_error_generic" msgid="352500456918362905">"No se ha podido cargar el estado"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Se ha producido un error. Vuelve a intentarlo."</string>
<string name="controls_in_progress" msgid="4421080500238215939">"En curso"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 0d640e1..ede01b7 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -92,7 +92,7 @@
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"Ekraanisalvestuse töötlemine"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"Pooleli märguanne ekraanikuva salvestamise seansi puhul"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"Kas alustada salvestamist?"</string>
- <string name="screenrecord_description" msgid="1123231719680353736">"Heli salvestamise ajal võib Androidi süsteem jäädvustada tundlikku teavet, mis on ekraanikuval nähtav või mida seadmes esitatakse. See hõlmab paroole, makseteavet, fotosid, sõnumeid ja heli."</string>
+ <string name="screenrecord_description" msgid="1123231719680353736">"Salvestamise ajal võib Androidi süsteem jäädvustada tundlikku teavet, mis on ekraanikuval nähtav või mida seadmes esitatakse. See hõlmab paroole, makseteavet, fotosid, sõnumeid ja heli."</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Heli salvestamine"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Seadme heli"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Seadmest pärinev heli, nt muusika, kõned ja helinad"</string>
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Teisalda üles paremale"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Teisalda alla vasakule"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Teisalda alla paremale"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Loobu"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Ära kuva vestlust mullina"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Vestelge mullide abil"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Uued vestlused kuvatakse hõljuvate ikoonidena ehk mullidena. Puudutage mulli avamiseks. Lohistage mulli, et seda liigutada."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Pühkige sõrmega, et näha rohkem"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Soovituste laadimine"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Sulge see meediaseanss"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Jätka"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Passiivne, vaadake rakendust"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Viga, proovitakse uuesti …"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Seade on eemaldatud"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Ei leitud"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Juhtelement pole saadaval"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Seadmele <xliff:g id="DEVICE">%1$s</xliff:g> ei pääsenud juurde. Kontrollige rakendust <xliff:g id="APPLICATION">%2$s</xliff:g> ja veenduge, et juhtelement oleks endiselt saadaval ning rakenduse seaded poleks muutunud."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Ava rakendus"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Olekut ei saa laadida"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Ilmnes viga, proovige uuesti"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Pooleli"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 1cb3148..641d031 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Eraman goialdera, eskuinetara"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Eraman behealdera, ezkerretara"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Eraman behealdera, eskuinetara"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Baztertu"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Ez erakutsi elkarrizketak burbuila gisa"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Txateatu burbuilen bidez"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Elkarrizketa berriak ikono gainerakor edo burbuila gisa agertzen dira. Sakatu burbuila irekitzeko. Arrasta ezazu mugitzeko."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Pasatu hatza aukera gehiago ikusteko"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Gomendioak kargatzen"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Itxi multimedia-saio hau"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Berrekin"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktibo; egiaztatu aplikazioa"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Errorea. Berriro saiatzen…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Gailua kendu da"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Ez da aurkitu"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Ez dago erabilgarri kontrolatzeko aukera"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Ezin izan da atzitu <xliff:g id="DEVICE">%1$s</xliff:g>. Joan <xliff:g id="APPLICATION">%2$s</xliff:g> aplikaziora, eta ziurtatu kontrolatzeko aukera oraindik ere erabilgarri dagoela eta aplikazioaren ezarpenak ez direla aldatu."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Ireki aplikazioa"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Ezin da kargatu egoera"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Errorea. Saiatu berriro."</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Abian"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 986015e..eec54de 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"انتقال به بالا سمت چپ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"انتقال به پایین سمت راست"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"انتقال به پایین سمت چپ"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"رد کردن"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"مکالمه در حباب نشان داده نشود"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"گپ بااستفاده از ابزارک اعلان"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"مکالمههای جدید بهصورت نمادهای شناور یا ابزارک اعلان نشان داده شوند. برای باز کردن ابزارک اعلان ضربه بزنید. برای جابهجایی، آن را بکشید."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"برای دیدن موارد بیشتر، تند بکشید"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"درحال بار کردن توصیهها"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"بستن این جلسه رسانه"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"ازسرگیری"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"غیرفعال، برنامه را بررسی کنید"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"خطا، درحال تلاش مجدد…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"دستگاه برداشته شد"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"پیدا نشد"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"کنترل دردسترس نیست"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"دسترسی به <xliff:g id="DEVICE">%1$s</xliff:g> ممکن نیست. برنامه <xliff:g id="APPLICATION">%2$s</xliff:g> را بررسی کنید تا مطمئن شوید کنترل هنوز دردسترس باشد و تنظیمات برنامه تغییر نکرده باشد."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"بازکردن برنامه"</string>
<string name="controls_error_generic" msgid="352500456918362905">"وضعیت بار نشد"</string>
<string name="controls_error_failed" msgid="960228639198558525">"خطا، دوباره امتحان کنید"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"درحال انجام"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index be04730..ee7ed70 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Siirrä oikeaan yläreunaan"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Siirrä vasempaan alareunaan"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Siirrä oikeaan alareunaan"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Ohita"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Älä näytä kuplia keskusteluista"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chattaile kuplien avulla"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Uudet keskustelut näkyvät kelluvina kuvakkeina tai kuplina. Avaa kupla napauttamalla. Siirrä sitä vetämällä."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Pyyhkäise nähdäksesi lisää"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Ladataan suosituksia"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Sulje tämä median käyttökerta"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Jatka"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Epäaktiivinen, tarkista sovellus"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Virhe, yritetään uudelleen…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Laite poistettu"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Ei löydy"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Ohjain ei ole käytettävissä"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Ei pääsyä: <xliff:g id="DEVICE">%1$s</xliff:g>. Avaa <xliff:g id="APPLICATION">%2$s</xliff:g> ja tarkista, että ohjain on edelleen käytettävissä ja että sovelluksen asetukset eivät ole muuttuneet."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Avaa sovellus"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Tilaa ei voi ladata"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Virhe, yritä uudelleen"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Käynnissä"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index a80e2d3..c71ab7e 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Déplacer dans coin sup. droit"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Déplacer dans coin inf. gauche"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Déplacer dans coin inf. droit"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Fermer"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Ne pas afficher les conversations dans des bulles"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Clavarder en utilisant des bulles"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Les nouvelles conversations s\'affichent sous forme d\'icônes flottantes (de bulles). Touchez une bulle pour l\'ouvrir. Faites-la glisser pour la déplacer."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Balayez l\'écran pour en afficher davantage"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Chargement des recommandations…"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Fermer cette session multimédia"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifiez l\'appli"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erreur, nouvelle tentative…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Appareil supprimé"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Introuvable"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"La commande n\'est pas accessible"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Impossible d\'accéder à <xliff:g id="DEVICE">%1$s</xliff:g>. Vérifiez l\'application <xliff:g id="APPLICATION">%2$s</xliff:g> pour vous assurer que la commande est toujours offerte et que les paramètres de l\'application n\'ont pas changé."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Ouvrir"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Impossible de charger l\'état"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Erreur. Veuillez réessayer."</string>
<string name="controls_in_progress" msgid="4421080500238215939">"En cours"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index b95cf57..4c69c86 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Déplacer en haut à droite"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Déplacer en bas à gauche"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Déplacer en bas à droite"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Ignorer"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Ne pas afficher la conversations dans des bulles"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chatter en utilisant des bulles"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Les nouvelles conversations s\'affichent sous forme d\'icônes flottantes ou bulles. Appuyez sur la bulle pour l\'ouvrir. Faites-la glisser pour la déplacer."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Balayer l\'écran pour voir plus d\'annonces"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Chargement des recommandations"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Fermer cette session multimédia"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Délai expiré, vérifier l\'appli"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erreur. Nouvelle tentative…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Appareil supprimé"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Introuvable"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Commande indisponible"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Impossible d\'accéder à \"<xliff:g id="DEVICE">%1$s</xliff:g>\". Vérifiez l\'application <xliff:g id="APPLICATION">%2$s</xliff:g> pour vous assurer que la commande est toujours disponible et que les paramètres de l\'application n\'ont pas changé."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Ouvrir l\'application"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Impossible de charger l\'état"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Erreur. Veuillez réessayer."</string>
<string name="controls_in_progress" msgid="4421080500238215939">"En cours"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 960e416..d80bd95 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Mover á parte superior dereita"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Mover á parte infer. esquerda"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Mover á parte inferior dereita"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Ignorar"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Non mostrar a conversa como burbulla"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chatear usando burbullas"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"As conversas novas aparecen como iconas flotantes ou burbullas. Toca para abrir a burbulla e arrastra para movela."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Pasar o dedo para ver máis"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Cargando recomendacións"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Pechar esta sesión multimedia"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactivo. Comproba a app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erro. Tentando de novo…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Quitouse o dispositivo"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Non se atopou"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"O control non está dispoñible"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Non se puido acceder a: <xliff:g id="DEVICE">%1$s</xliff:g>. Comproba a aplicación <xliff:g id="APPLICATION">%2$s</xliff:g> para asegurarte de que o control aínda estea dispoñible e que non se modificase a configuración da aplicación."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Abrir aplicación"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Non se puido cargar o estado"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Erro. Téntao de novo"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"En curso"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 4936b7b..c641208 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"ઉપર જમણે ખસેડો"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"નીચે ડાબે ખસેડો"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"નીચે જમણે ખસેડો"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"છોડી દો"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"વાતચીતને બબલ કરશો નહીં"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"બબલનો ઉપયોગ કરીને ચેટ કરો"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"નવી વાતચીત ફ્લોટિંગ આઇકન અથવા બબલ જેવી દેખાશે. બબલને ખોલવા માટે ટૅપ કરો. તેને ખસેડવા માટે ખેંચો."</string>
@@ -1013,17 +1014,14 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"સિસ્ટમ નૅવિગેશન અપડેટ કર્યું. ફેરફારો કરવા માટે, સેટિંગ પર જાઓ."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"સિસ્ટમ નૅવિગેશનને અપડેટ કરવા માટે સેટિંગ પર જાઓ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"સ્ટૅન્ડબાય"</string>
- <!-- no translation found for priority_onboarding_title (2893070698479227616) -->
- <skip />
- <!-- no translation found for priority_onboarding_behavior (5342816047020432929) -->
- <skip />
+ <string name="priority_onboarding_title" msgid="2893070698479227616">"વાતચીતને પ્રાધાન્યતા ધરાવતી તરીકે સેટ કરી"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"પ્રાધાન્યતા ધરાવતી વાતચીતો:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"વાતચીત વિભાગની ટોચ પર બતાવો"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"લૉક સ્ક્રીન પર પ્રોફાઇલ ફોટો બતાવો"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"ઍપની ટોચ પર તરતા બબલ તરીકે દેખાય છે"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"ખલેલ પાડશો નહીં સેટિંગમાં હસ્તક્ષેપ કરી શકે છે"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"સમજાઈ ગયું"</string>
- <!-- no translation found for priority_onboarding_settings_button_title (6663601574303585927) -->
- <skip />
+ <string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"સેટિંગ"</string>
<string name="magnification_overlay_title" msgid="6584179429612427958">"વિસ્તૃતીકરણ ઓવરલે વિંડો"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"વિસ્તૃતીકરણ વિંડો"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"વિસ્તૃતીકરણ વિંડોના નિયંત્રણો"</string>
@@ -1065,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"વધુ જોવા માટે સ્વાઇપ કરો"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"સુઝાવ લોડ કરી રહ્યાં છીએ"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"આ મીડિયા સત્રને બંધ કરો"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"ફરી શરૂ કરો"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"નિષ્ક્રિય, ઍપને ચેક કરો"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"ભૂલ, ફરી પ્રયાસ કરી રહ્યા છીએ…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"ડિવાઇસ કાઢી નાખ્યું"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"મળ્યું નથી"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"નિયંત્રણ ઉપલબ્ધ નથી"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g>ને ઍક્સેસ કરી શક્યાં નહીં. નિયંત્રણ હજી પણ ઉપલબ્ધ છે અને તે કે ઍપના સેટિંગ બદલાયા નથી તેની ખાતરી કરવા માટે <xliff:g id="APPLICATION">%2$s</xliff:g> ઍપ ચેક કરો."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"ઍપ ખોલો"</string>
<string name="controls_error_generic" msgid="352500456918362905">"સ્ટેટસ લોડ કરી શકાતું નથી"</string>
<string name="controls_error_failed" msgid="960228639198558525">"ભૂલ, ફરીથી પ્રયાસ કરો"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"પ્રક્રિયા ચાલુ છે"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 1fcfcc4..4288407 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -1004,7 +1004,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"सबसे ऊपर दाईं ओर ले जाएं"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"बाईं ओर सबसे नीचे ले जाएं"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"सबसे नीचे दाईं ओर ले जाएं"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"खारिज करें"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"बातचीत को बबल न करें"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"बबल्स का इस्तेमाल करके चैट करें"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"नई बातचीत फ़्लोटिंग आइकॉन या बबल्स की तरह दिखेंगी. बबल को खोलने के लिए टैप करें. इसे एक जगह से दूसरी जगह ले जाने के लिए खींचें और छोड़ें."</string>
@@ -1064,9 +1065,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"ज़्यादा देखने के लिए स्वाइप करें"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"सुझाव लोड हो रहे हैं"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"इस मीडिया सेशन को बंद करें"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"फिर से शुरू करें"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"काम नहीं कर रहा, ऐप जांचें"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"कोई गड़बड़ी हुई, फिर से कोशिश की जा रही है…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"डिवाइस हटाया गया"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"कंट्रोल नहीं मिला"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"कंट्रोल मौजूद नहीं है"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> ऐक्सेस नहीं किया जा सका. <xliff:g id="APPLICATION">%2$s</xliff:g> ऐप्लिकेशन देखें, ताकि यह पक्का किया जा सके कि कंट्रोल अब भी मौजूद है और सेटिंग में कोई बदलाव नहीं हुआ है."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"ऐप्लिकेशन खोलें"</string>
<string name="controls_error_generic" msgid="352500456918362905">"स्थिति लोड नहीं की जा सकती"</string>
<string name="controls_error_failed" msgid="960228639198558525">"गड़बड़ी हुई, फिर से कोशिश करें"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"जारी है"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index c918dca..b8b784c 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -1007,7 +1007,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Premjesti u gornji desni kut"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Premjesti u donji lijevi kut"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Premjestite u donji desni kut"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Odbaci"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Zaustavi razgovor u oblačićima"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chatanje pomoću oblačića"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Novi razgovori pojavljuju se kao pomične ikone ili oblačići. Dodirnite za otvaranje oblačića. Povucite da biste ga premjestili."</string>
@@ -1068,9 +1069,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Prijeđite prstom da vidite više"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Učitavanje preporuka"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Zatvorite ovu medijsku sesiju"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Nastavi"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, provjerite aplik."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Pogreška, pokušavamo ponovo…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Uređaj je uklonjen"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Nije pronađeno"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrola nije dostupna"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Nije moguće pristupiti uređaju: <xliff:g id="DEVICE">%1$s</xliff:g>. U aplikaciji <xliff:g id="APPLICATION">%2$s</xliff:g> provjerite je li kontrola i dalje dostupna te potvrdite da se postavke aplikacije nisu promijenile."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Otvori apl."</string>
<string name="controls_error_generic" msgid="352500456918362905">"Status se ne može učitati"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Pogreška, pokušajte ponovo"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"U tijeku"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 2a991f1..551fcd8 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Áthelyezés fel és jobbra"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Áthelyezés le és balra"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Áthelyezés le és jobbra"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Elvetés"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Ne jelenjen meg a beszélgetés buborékban"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Buborékokat használó csevegés"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Az új beszélgetések lebegő ikonként, vagyis buborékként jelennek meg. A buborék megnyitásához koppintson rá. Áthelyezéshez húzza a kívánt helyre."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Továbbiak megtekintéséhez csúsztasson"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Javaslatok betöltése…"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Médiamunkamenet bezárása"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Folytatás"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktív, ellenőrizze az appot"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Hiba, újrapróbálkozás…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Eszköz eltávolítva"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Nem található"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Nem hozzáférhető vezérlő"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Nem lehet hozzáférni a következőhöz: <xliff:g id="DEVICE">%1$s</xliff:g>. Ellenőrizze a(z) <xliff:g id="APPLICATION">%2$s</xliff:g> alkalmazást, és győződjön meg arról, hogy a vezérlő továbbra is rendelkezésre áll, illetve nem változtak az alkalmazás beállításai."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"App megnyitása"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Állapot betöltése sikertelen"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Hiba történt. Próbálja újra."</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Folyamatban"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 908231a..730f115 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Տեղափոխել վերև՝ աջ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Տեղափոխել ներքև՝ ձախ"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Տեղափոխել ներքև՝ աջ"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Փակել"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Զրույցը չցուցադրել ամպիկի տեսքով"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Զրուցել ամպիկների միջոցով"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Նոր խոսակցությունները կհայտնվեն լողացող պատկերակների կամ ամպիկների տեսքով։ Հպեք՝ ամպիկը բացելու համար։ Քաշեք՝ այն տեղափոխելու համար։"</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Սահեցրեք մատը՝ ավելին իմանալու համար"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Բեռնման խորհուրդներ"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Փակել աշխատաշրջանը"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Շարունակել"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Ակտիվ չէ, ստուգեք հավելվածը"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Սխալ. նորից ենք փորձում…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Սարքը հեռացված է"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Չի գտնվել"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Կառավարման տարրը հասանելի չէ"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> սարքն անհասանելի է։ Ստուգեք <xliff:g id="APPLICATION">%2$s</xliff:g> հավելվածը՝ համոզվելու, որ կառավարման տարրը դեռ հասանելի է և հավելվածի կարգավորումները չեն փոխվել։"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Բացել հավելվածը"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Չհաջողվեց բեռնել կարգավիճակը"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Սխալ առաջացավ։ Նորից փորձեք։"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Ընթացքի մեջ է"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 2e11e42..3614cb4 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Pindahkan ke kanan atas"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Pindahkan ke kiri bawah"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Pindahkan ke kanan bawah"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Tutup"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Jangan gunakan percakapan balon"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chat dalam tampilan balon"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Percakapan baru muncul sebagai ikon mengambang, atau balon. Ketuk untuk membuka balon. Tarik untuk memindahkannya."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Geser untuk melihat selengkapnya"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Memuat rekomendasi"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Tutup sesi media ini"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Lanjutkan"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nonaktif, periksa aplikasi"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Error, mencoba lagi..."</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Perangkat dihapus"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Tidak ditemukan"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrol tidak tersedia"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Tidak dapat mengakses <xliff:g id="DEVICE">%1$s</xliff:g>. Periksa aplikasi <xliff:g id="APPLICATION">%2$s</xliff:g> untuk memastikan kontrol masih tersedia dan bahwa setelan aplikasi tidak berubah."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Buka aplikasi"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Tidak dapat memuat status"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Error, coba lagi"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Dalam proses"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 773bda7..224164c 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Færa efst til hægri"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Færa neðst til vinstri"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Færðu neðst til hægri"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Hunsa"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Ekki setja samtal í blöðru"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Spjalla með blöðrum"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Ný samtöl birtast sem fljótandi tákn eða blöðrur. Ýttu til að opna blöðru. Dragðu hana til að færa."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Strjúktu til að sjá meira"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Hleður tillögum"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Loka þessari efnislotu"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Halda áfram"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Óvirkt, athugaðu forrit"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Villa, reynir aftur…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Tæki fjarlægt"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Fannst ekki"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Stýring er ekki tiltæk"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Ekki tókst að tengjast <xliff:g id="DEVICE">%1$s</xliff:g>. Athugaðu <xliff:g id="APPLICATION">%2$s</xliff:g> forritið til að ganga úr skugga um að stýringin sé enn í boði og að stillingum forritsins hafi ekki verið breytt."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Opna forrit"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Ekki er hægt að hlaða stöðu"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Villa, reyndu aftur"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Í gangi"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 0844284..f9fcda4 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -721,7 +721,7 @@
<string name="notification_priority_title" msgid="2079708866333537093">"Priorità"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> non supporta le funzionalità delle conversazioni"</string>
<string name="bubble_overflow_empty_title" msgid="3120029421991510842">"Nessuna bolla recente"</string>
- <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Le bolle recenti e ignorate verranno visualizzate qui"</string>
+ <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Le bolle recenti e ignorate appariranno qui"</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Impossibile modificare queste notifiche."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Qui non è possibile configurare questo gruppo di notifiche"</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"Notifica inviata al proxy"</string>
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Sposta in alto a destra"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Sposta in basso a sinistra"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Sposta in basso a destra"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Ignora"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Non utilizzare bolle per la conversazione"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chatta utilizzando le bolle"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Le nuove conversazioni vengono visualizzate come icone mobili o bolle. Tocca per aprire la bolla. Trascinala per spostarla."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Scorri per vedere altro"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Caricamento dei consigli"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Chiudi questa sessione multimediale"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Riprendi"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inattivo, controlla l\'app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Errore. Nuovo tentativo…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Dispositivo rimosso"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Controllo non trovato"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Il controllo non è disponibile"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Impossibile accedere a: <xliff:g id="DEVICE">%1$s</xliff:g>. Verifica nell\'app <xliff:g id="APPLICATION">%2$s</xliff:g> che il controllo sia ancora disponibile e che le impostazioni dell\'app non siano cambiate."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Apri app"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Impossibile caricare lo stato"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Errore. Riprova"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"In corso"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index f23254a..172919c 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -1012,7 +1012,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"העברה לפינה הימנית העליונה"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"העברה לפינה השמאלית התחתונה"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"העברה לפינה הימנית התחתונה"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"סגירה"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"אין להציג בועות לשיחה"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"לדבר בצ\'אט באמצעות בועות"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"שיחות חדשות מופיעות כסמלים צפים, או בועות. יש להקיש כדי לפתוח בועה. יש לגרור כדי להזיז אותה."</string>
@@ -1023,17 +1024,14 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"הניווט במערכת עודכן. אפשר לערוך שינויים דרך ההגדרות."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"יש לעבור להגדרות כדי לעדכן את הניווט במערכת"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"המתנה"</string>
- <!-- no translation found for priority_onboarding_title (2893070698479227616) -->
- <skip />
- <!-- no translation found for priority_onboarding_behavior (5342816047020432929) -->
- <skip />
+ <string name="priority_onboarding_title" msgid="2893070698479227616">"השיחה הוגדרה כבעלת עדיפות גבוהה"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"שיחות בעדיפות גבוהה:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"מופיעות בחלק העליון של קטע השיחות"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"מציגות תמונת פרופיל במסך הנעילה"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"מופיעות כבועה צפה מעל האפליקציות שלך"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"גוברות על ההגדרה \'נא לא להפריע\'"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"הבנתי"</string>
- <!-- no translation found for priority_onboarding_settings_button_title (6663601574303585927) -->
- <skip />
+ <string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"הגדרות"</string>
<string name="magnification_overlay_title" msgid="6584179429612427958">"חלון ליצירת שכבת-על להגדלה"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"חלון הגדלה"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"בקרות של חלון ההגדלה"</string>
@@ -1077,9 +1075,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"יש להחליק כדי להציג עוד פריטים"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"בטעינת המלצות"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"סגירת הסשן הזה של המדיה"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"המשך"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"לא פעיל, יש לבדוק את האפליקציה"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"שגיאה, מתבצע ניסיון חוזר…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"המכשיר הוסר"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"לא נמצא"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"הפקד לא זמין"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"לא ניתן להתחבר אל <xliff:g id="DEVICE">%1$s</xliff:g>. יש לבדוק את האפליקציה <xliff:g id="APPLICATION">%2$s</xliff:g> כדי לוודא שהפקד עדיין זמין ושהגדרות האפליקציה לא השתנו."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"לפתיחת האפליקציה"</string>
<string name="controls_error_generic" msgid="352500456918362905">"לא ניתן לטעון את הסטטוס"</string>
<string name="controls_error_failed" msgid="960228639198558525">"שגיאה, יש לנסות שוב"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"בתהליך"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 6e7555a..a2bb39c 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -1002,9 +1002,10 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"右上に移動"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"左下に移動"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"右下に移動"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"閉じる"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"会話をバブルで表示しない"</string>
- <string name="bubbles_user_education_title" msgid="5547017089271445797">"チャットでのバブルの使用"</string>
+ <string name="bubbles_user_education_title" msgid="5547017089271445797">"チャットでバブルを使う"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"新しい会話はフローティング アイコン(バブル)として表示されます。タップするとバブルが開きます。ドラッグしてバブルを移動できます。"</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"いつでもバブルを管理"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"このアプリからのバブルをオフにするには、[管理] をタップしてください"</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"スワイプすると他の構造が表示されます"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"候補を読み込んでいます"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"このメディア セッションを閉じる"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"再開"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"無効: アプリをご確認ください"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"エラー。再試行しています…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"デバイスを削除しました"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"見つかりませんでした"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"コントロールを使用できません"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"「<xliff:g id="DEVICE">%1$s</xliff:g>」にアクセスできませんでした<xliff:g id="APPLICATION">%2$s</xliff:g> アプリで、コントロールが使用可能な状態でアプリの設定が変更されていないことをご確認ください。"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"アプリを開く"</string>
<string name="controls_error_generic" msgid="352500456918362905">"ステータスを読み込めません"</string>
<string name="controls_error_failed" msgid="960228639198558525">"エラー: もう一度お試しください"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"処理中"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 4aea87b..37b5ec9 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"გადაანაცვლეთ ზევით და მარჯვნივ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"ქვევით და მარცხნივ გადატანა"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"გადაანაცვ. ქვემოთ და მარჯვნივ"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"დახურვა"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"აიკრძალოს საუბრის ბუშტები"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"ჩეთი ბუშტების გამოყენებით"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"ახალი საუბრები გამოჩნდება როგორც მოტივტივე ხატულები ან ბუშტები. შეეხეთ ბუშტის გასახსნელად. გადაიტანეთ ჩავლებით."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"გადაფურცლეთ მეტის სანახავად"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"მიმდინარეობს რეკომენდაციების ჩატვირთვა"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"ამ მედია სესიის დახურვა"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"გაგრძელება"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"არააქტიურია, გადაამოწმეთ აპი"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"შეცდომა, ხელახალი მცდელობა…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"მოწყობილობა ამოიშალა"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"ვერ მოიძებნა"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"კონტროლი მიუწვდომელია"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g>-ზე წვდომა ვერ მოხერხდა. შეამოწმეთ <xliff:g id="APPLICATION">%2$s</xliff:g> აპი, რათა დარწმუნდეთ, რომ კონტროლი კვლავაც ხელმისაწვდომია და რომ აპის პარამეტრები არ შეცვლილა."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"აპის გახსნა"</string>
<string name="controls_error_generic" msgid="352500456918362905">"სტატუსი ვერ იტვირთება"</string>
<string name="controls_error_failed" msgid="960228639198558525">"შეცდომა, ისევ ცადეთ"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"მუშავდება"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index bb4ee6b..73f0e6c 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -274,7 +274,7 @@
<string name="accessibility_quick_settings_airplane_changed_off" msgid="8880183481476943754">"Ұшақ режимі өшірілді."</string>
<string name="accessibility_quick_settings_airplane_changed_on" msgid="6327378061894076288">"Ұшақ режимі қосылды."</string>
<string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"үнсіз"</string>
- <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3375848309132140014">"тек дабылдар"</string>
+ <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3375848309132140014">"оятқыштар ғана"</string>
<string name="accessibility_quick_settings_dnd" msgid="2415967452264206047">"Мазаламау."</string>
<string name="accessibility_quick_settings_dnd_changed_off" msgid="1457150026842505799">"\"Мазаламау\" режимі өшірілді."</string>
<string name="accessibility_quick_settings_dnd_changed_on" msgid="186315911607486129">"\"Мазаламау\" режимі қосылды."</string>
@@ -344,7 +344,7 @@
<string name="quick_settings_header_onboarding_text" msgid="1918085351115504765">"Басқа опцияларды көру үшін белгішелерді түртіп ұстап тұрыңыз"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"Мазаламау"</string>
<string name="quick_settings_dnd_priority_label" msgid="6251076422352664571">"Маңыздылары ғана"</string>
- <string name="quick_settings_dnd_alarms_label" msgid="1241780970469630835">"Тек дабылдар"</string>
+ <string name="quick_settings_dnd_alarms_label" msgid="1241780970469630835">"Оятқыштар ғана"</string>
<string name="quick_settings_dnd_none_label" msgid="8420869988472836354">"Толық тыныштық"</string>
<string name="quick_settings_bluetooth_label" msgid="7018763367142041481">"Bluetooth"</string>
<string name="quick_settings_bluetooth_multiple_devices_label" msgid="6595808498429809855">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g> құрылғылары)"</string>
@@ -462,7 +462,7 @@
<string name="interruption_level_none_with_warning" msgid="8394434073508145437">"Толық тыныштық. Экранды оқу құралдары да өшеді."</string>
<string name="interruption_level_none" msgid="219484038314193379">"Толық тыныштық"</string>
<string name="interruption_level_priority" msgid="661294280016622209">"Маңыздылары ғана"</string>
- <string name="interruption_level_alarms" msgid="2457850481335846959">"Тек дабылдар"</string>
+ <string name="interruption_level_alarms" msgid="2457850481335846959">"Оятқыштар ғана"</string>
<string name="interruption_level_none_twoline" msgid="8579382742855486372">"Толық\nтыныштық"</string>
<string name="interruption_level_priority_twoline" msgid="8523482736582498083">"Тек\nбасымдық"</string>
<string name="interruption_level_alarms_twoline" msgid="2045067991335708767">"Тек\nдабылдар"</string>
@@ -721,7 +721,7 @@
<string name="notification_priority_title" msgid="2079708866333537093">"Маңыздылығы"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> әңгімелесу функцияларын қолдамайды."</string>
<string name="bubble_overflow_empty_title" msgid="3120029421991510842">"Жақындағы қалқыма хабарлар жоқ"</string>
- <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Жақында ашылған және жабылған қалқыма хабарлар осы жерде көрсетіледі."</string>
+ <string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Соңғы және жабылған қалқыма хабарлар осы жерде көрсетіледі."</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Бұл хабарландыруларды өзгерту мүмкін емес."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Мұндай хабарландырулар бұл жерде конфигурацияланбайды."</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"Прокси-сервер арқылы жіберілген хабарландыру"</string>
@@ -1002,9 +1002,10 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Жоғары оң жаққа жылжыту"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Төменгі сол жаққа жылжыту"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Төменгі оң жаққа жылжыту"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Жабу"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Әңгіменің қалқыма хабары көрсетілмесін"</string>
- <string name="bubbles_user_education_title" msgid="5547017089271445797">"Сөйлесуге арналған қалқыма хабарлар"</string>
+ <string name="bubbles_user_education_title" msgid="5547017089271445797">"Қалқыма хабарлар арқылы сөйлесу"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Жаңа әңгімелер қалқыма белгішелер немесе хабарлар түрінде көрсетіледі. Қалқыма хабарды ашу үшін түртіңіз. Жылжыту үшін сүйреңіз."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Қалқыма хабарларды реттеу"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Бұл қолданбадан қалқыма хабарларды өшіру үшін \"Басқару\" түймесін түртіңіз."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Толығырақ ақпарат алу үшін сырғытыңыз."</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Жүктеуге қатысты ұсыныстар"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Мультимедиа сеансын жабу"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Жалғастыру"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Өшірулі. Қолданба тексеріңіз."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Қате, әрекет қайталануда…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Құрылғы өшірілді."</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Табылмады"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Басқару элементтері қолжетімді емес"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> ашылмады. Басқару элементтерінің әлі қолжетімді екенін және қолданба параметрлерінің өзгермегенін тексеру үшін <xliff:g id="APPLICATION">%2$s</xliff:g> қолданбасын қараңыз."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Қолданбаны ашу"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Күйді жүктеу мүмкін емес."</string>
<string name="controls_error_failed" msgid="960228639198558525">"Қате шықты. Қайталап көріңіз."</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Орындалуда"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index c00549c..47fd544 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"ផ្លាស់ទីទៅផ្នែកខាងលើខាងស្ដាំ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"ផ្លាស់ទីទៅផ្នែកខាងក្រោមខាងឆ្វេង"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"ផ្លាស់ទីទៅផ្នែកខាងក្រោមខាងស្ដាំ"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"ច្រានចោល"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"កុំបង្ហាញការសន្ទនាជាពពុះ"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"ជជែកដោយប្រើពពុះ"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"ការសន្ទនាថ្មីៗបង្ហាញជាពពុះ ឬរូបអណ្ដែត។ ចុច ដើម្បីបើកពពុះ។ អូស ដើម្បីផ្លាស់ទីពពុះនេះ។"</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"អូសដើម្បីមើលច្រើនទៀត"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"កំពុងផ្ទុកការណែនាំ"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"បិទវគ្គមេឌៀនេះ"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"បន្ត"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"អសកម្ម ពិនិត្យមើលកម្មវិធី"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"បញ្ហា កំពុងព្យាយាមម្ដងទៀត…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"បានលុបឧបករណ៍"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"រកមិនឃើញទេ"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"មិនអាចគ្រប់គ្រងបានទេ"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"មិនអាចចូលប្រើ <xliff:g id="DEVICE">%1$s</xliff:g> បានទេ។ សូមពិនិត្យមើលកម្មវិធី <xliff:g id="APPLICATION">%2$s</xliff:g> ដើម្បីប្រាកដថានៅតែអាចគ្រប់គ្រងបាន ហើយថាការកំណត់កម្មវិធីនេះមិនបានផ្លាស់ប្ដូរឡើយ។"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"បើកកម្មវិធី"</string>
<string name="controls_error_generic" msgid="352500456918362905">"មិនអាចផ្ទុកស្ថានភាពបានទេ"</string>
<string name="controls_error_failed" msgid="960228639198558525">"មានបញ្ហា សូមព្យាយាមម្តងទៀត"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"កំពុងដំណើរការ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 7b707b5..afa6052 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"ಬಲ ಮೇಲ್ಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"ಸ್ಕ್ರೀನ್ನ ಎಡ ಕೆಳಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"ಕೆಳಗಿನ ಬಲಭಾಗಕ್ಕೆ ಸರಿಸಿ"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"ವಜಾಗೊಳಿಸಿ"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"ಸಂಭಾಷಣೆಯನ್ನು ಬಬಲ್ ಮಾಡಬೇಡಿ"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"ಬಬಲ್ಸ್ ಬಳಸಿ ಚಾಟ್ ಮಾಡಿ"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"ಹೊಸ ಸಂಭಾಷಣೆಗಳು ತೇಲುವ ಐಕಾನ್ಗಳು ಅಥವಾ ಬಬಲ್ಸ್ ಆಗಿ ಗೋಚರಿಸುತ್ತವೆ. ಬಬಲ್ ತೆರೆಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ. ಅದನ್ನು ಡ್ರ್ಯಾಗ್ ಮಾಡಲು ಎಳೆಯಿರಿ."</string>
@@ -1013,17 +1014,14 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"ಸಿಸ್ಟಂ ನ್ಯಾವಿಗೇಷನ ಅಪ್ಡೇಟ್ ಮಾಡಲಾಗಿದೆ ಬದಲಾವಣೆಗಳನ್ನು ಮಾಡಲು, ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಹೋಗಿ."</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"ಸಿಸ್ಟಂ ನ್ಯಾವಿಗೇಷನ್ ಅಪ್ಡೇಟ್ ಮಾಡಲು ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಹೋಗಿ"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"ಸ್ಟ್ಯಾಂಡ್ಬೈ"</string>
- <!-- no translation found for priority_onboarding_title (2893070698479227616) -->
- <skip />
- <!-- no translation found for priority_onboarding_behavior (5342816047020432929) -->
- <skip />
+ <string name="priority_onboarding_title" msgid="2893070698479227616">"ಸಂವಾದವನ್ನು ಆದ್ಯತೆಯಾಗಿ ಹೊಂದಿಸಲಾಗಿದೆ"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"ಆದ್ಯತೆಯ ಸಂವಾದಗಳು:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"ಸಂಭಾಷಣೆ ವಿಭಾಗದ ಮೇಲ್ಭಾಗದಲ್ಲಿ ತೋರಿಸಿ"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"ಲಾಕ್ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಪ್ರೊಫೈಲ್ ಚಿತ್ರವನ್ನು ತೋರಿಸಿ"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"ಆ್ಯಪ್ಗಳ ಮೇಲ್ಭಾಗದಲ್ಲಿ ತೇಲುವ ಬಬಲ್ನಂತೆ ಗೋಚರಿಸಲಿ"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"ಅಡಚಣೆ ಮಾಡಬೇಡ ಅನ್ನು ಅಡ್ಡಿಪಡಿಸಿ"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"ಅರ್ಥವಾಯಿತು"</string>
- <!-- no translation found for priority_onboarding_settings_button_title (6663601574303585927) -->
- <skip />
+ <string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="magnification_overlay_title" msgid="6584179429612427958">"ವರ್ಧನೆಯ ಓವರ್ಲೇ ವಿಂಡೋ"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"ವರ್ಧನೆಯ ವಿಂಡೋ"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"ವರ್ಧನೆಯ ವಿಂಡೋ ನಿಯಂತ್ರಣಗಳು"</string>
@@ -1065,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"ಇನ್ನಷ್ಟು ನೋಡಲು ಸ್ವೈಪ್ ಮಾಡಿ"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ಶಿಫಾರಸುಗಳು ಲೋಡ್ ಆಗುತ್ತಿವೆ"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"ಈ ಮಾಧ್ಯಮ ಸೆಶನ್ ಅನ್ನು ಮುಚ್ಚಿರಿ"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"ಪುನರಾರಂಭಿಸಿ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ನಿಷ್ಕ್ರಿಯ, ಆ್ಯಪ್ ಪರಿಶೀಲಿಸಿ"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"ದೋಷ, ಮರುಪ್ರಯತ್ನಿಸಲಾಗುತ್ತಿದೆ…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"ಸಾಧನವನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"ಕಂಡುಬಂದಿಲ್ಲ"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"ನಿಯಂತ್ರಣ ಲಭ್ಯವಿಲ್ಲ"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ನಿಯಂತ್ರಣ ಈಗಲೂ ಲಭ್ಯವಿದೆಯೇ ಮತ್ತು <xliff:g id="APPLICATION">%2$s</xliff:g> ಆ್ಯಪ್ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಬದಲಾಯಿಸಲಾಗಿಲ್ಲ ಎಂಬುದನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಲು ಆ್ಯಪ್ ಅನ್ನು ಪರಿಶೀಲಿಸಿ."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"ಆ್ಯಪ್ ತೆರೆಯಿರಿ"</string>
<string name="controls_error_generic" msgid="352500456918362905">"ಸ್ಥಿತಿ ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
<string name="controls_error_failed" msgid="960228639198558525">"ದೋಷ, ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"ಪ್ರಗತಿಯಲ್ಲಿದೆ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 263c4dd..a75c230 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -720,7 +720,7 @@
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"설정"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"우선순위"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱은 대화 기능을 지원하지 않습니다."</string>
- <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"최근에 닫은 대화창 없음"</string>
+ <string name="bubble_overflow_empty_title" msgid="3120029421991510842">"최근 대화창 없음"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"최근 대화창과 내가 닫은 대화창이 여기에 표시됩니다."</string>
<string name="notification_unblockable_desc" msgid="2073030886006190804">"이 알림은 수정할 수 없습니다."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"이 알림 그룹은 여기에서 설정할 수 없습니다."</string>
@@ -1002,9 +1002,10 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"오른쪽 상단으로 이동"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"왼쪽 하단으로 이동"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"오른쪽 하단으로 이동"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"닫기"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"대화를 대화창으로 표시하지 않음"</string>
- <string name="bubbles_user_education_title" msgid="5547017089271445797">"대화창을 사용하여 채팅하세요"</string>
+ <string name="bubbles_user_education_title" msgid="5547017089271445797">"대화창으로 채팅하기"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"새로운 대화가 플로팅 아이콘인 대화창으로 표시됩니다. 대화창을 열려면 탭하세요. 드래그하여 이동할 수 있습니다."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"언제든지 대화창을 제어하세요"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"이 앱에서 대화창을 사용 중지하려면 관리를 탭하세요."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"자세히 보려면 스와이프하세요."</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"추천 제어 기능 로드 중"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"이 미디어 세션 닫기"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"다시 시작"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"비활성. 앱을 확인하세요."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"오류 발생, 다시 시도 중…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"기기가 삭제됨"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"찾을 수 없음"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"컨트롤을 사용할 수 없음"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g>에 액세스할 수 없습니다. <xliff:g id="APPLICATION">%2$s</xliff:g> 앱에서 컨트롤을 계속 사용할 수 있는지와 앱 설정이 변경되지 않았는지 확인하세요."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"앱 열기"</string>
<string name="controls_error_generic" msgid="352500456918362905">"통계를 로드할 수 없음"</string>
<string name="controls_error_failed" msgid="960228639198558525">"오류. 다시 시도하세요."</string>
<string name="controls_in_progress" msgid="4421080500238215939">"진행 중"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index dcd10cc..a0f532a 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Жогорку оң жакка жылдырыңыз"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Төмөнкү сол жакка жылдыруу"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Төмөнкү оң жакка жылдырыңыз"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Жабуу"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Жазышуу калкып чыкма билдирмеде көрүнбөсүн"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Калкып чыкма билдирмелер аркылуу маектешүү"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Жаңы жазышуулар калкыма сүрөтчөлөр же калкып чыкма билдирмелер болуп көрүнөт. Калкып чыкма билдирмелерди ачуу үчүн таптап коюңуз. Жылдыруу үчүн сүйрөңүз."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Дагы көрүү үчүн экранды сүрүп коюңуз"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Сунуштар жүктөлүүдө"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Бул медиа сеансын жабуу"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Улантуу"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Жигерсиз. Колдонмону текшериңиз"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Ката, дагы аракет жасалууда…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Түзмөктү көзөмөлдөө өчүрүлдү"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Табылган жок"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Көзөмөл жеткиликтүү эмес"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> түзмөгүнө кирүү мүмкүнчүлүгү жок. <xliff:g id="APPLICATION">%2$s</xliff:g> колдонмосуна өтүп, көзөмөл жеткиликтүү экенин жана колдонмонун жөндөөлөрү өзгөрбөгөнүн текшериңиз."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Колдонмону ачуу"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Абалы жүктөлгөн жок"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Ката, кайталап көрүңүз"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Аткарылууда"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index a7e9d8d..829d39a 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"ຍ້າຍຂວາເທິງ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"ຍ້າຍຊ້າຍລຸ່ມ"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"ຍ້າຍຂວາລຸ່ມ"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"ປິດໄວ້"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"ຢ່າໃຊ້ຟອງໃນການສົນທະນາ"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"ສົນທະນາໂດຍໃຊ້ຟອງ"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"ການສົນທະນາໃໝ່ຈະປາກົດເປັນໄອຄອນ ຫຼື ຟອງແບບລອຍ. ແຕະເພື່ອເປີດຟອງ. ລາກເພື່ອຍ້າຍມັນ."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"ປັດເພື່ອເບິ່ງເພີ່ມເຕີມ"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ກຳລັງໂຫຼດຄຳແນະນຳ"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"ປິດເຊດຊັນມີເດຍນີ້"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"ສືບຕໍ່"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ບໍ່ເຮັດວຽກ, ກະລຸນາກວດສອບແອັບ"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"ຜິດພາດ, ກໍາລັງລອງໃໝ່…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"ລຶບອຸປະກອນອອກແລ້ວ"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"ບໍ່ພົບ"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"ບໍ່ສາມາດໃຊ້ການຄວບຄຸມໄດ້"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"ບໍ່ສາມາດເຂົ້າເຖິງ <xliff:g id="DEVICE">%1$s</xliff:g> ໄດ້. ກະລຸນາກວດສອບແອັບ <xliff:g id="APPLICATION">%2$s</xliff:g> ເພື່ອເບິ່ງວ່າຍັງສາມາດໃຊ້ການຄວບຄຸມໄດ້ຫຼືບໍ່ ແລະ ຍັງບໍ່ໄດ້ປ່ຽນການຕັ້ງຄ່າແອັບເທື່ອ."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"ເປີດແອັບ"</string>
<string name="controls_error_generic" msgid="352500456918362905">"ບໍ່ສາມາດໂຫຼດສະຖານະໄດ້"</string>
<string name="controls_error_failed" msgid="960228639198558525">"ຜິດພາດ, ກະລຸນາລອງໃໝ່"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"ກຳລັງດຳເນີນການຢູ່"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index a090319..de79394 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -1012,7 +1012,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Perkelti į viršų dešinėje"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Perkelti į apačią kairėje"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Perkelti į apačią dešinėje"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Atmesti"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nerodyti pokalbio burbule"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Pokalbis naudojant burbulus"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Nauji pokalbiai rodomi kaip slankiosios piktogramos arba burbulus. Palieskite, kad atidarytumėte burbulą. Vilkite, kad perkeltumėte."</string>
@@ -1074,9 +1075,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Perbraukite, kad peržiūrėtumėte daugiau"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Įkeliamos rekomendacijos"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Uždaryti šį medijos seansą"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Tęsti"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktyvu, patikrinkite progr."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Klaida, bandoma iš naujo…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Įrenginys pašalintas"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Nerasta"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Valdiklis nepasiekiamas"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Nepavyko pasiekti: <xliff:g id="DEVICE">%1$s</xliff:g>. Eikite į programą „<xliff:g id="APPLICATION">%2$s</xliff:g>“ ir įsitikinkite, kad valdiklis vis dar pasiekiamas ir kad programos nustatymai nepakeisti."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Atidaryti programą"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Nepavyko įkelti būsenos"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Klaida, bandykite dar kartą"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Vyksta"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index f107de9c..ba6b895 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -1007,7 +1007,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Pārvietot augšpusē pa labi"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Pārvietot apakšpusē pa kreisi"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Pārvietot apakšpusē pa labi"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Nerādīt"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nerādīt sarunu burbuļos"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Tērzēšana, izmantojot burbuļus"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Jaunas sarunas tiek rādītas kā peldošas ikonas vai burbuļi. Pieskarieties, lai atvērtu burbuli. Velciet, lai to pārvietotu."</string>
@@ -1068,9 +1069,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Velciet, lai skatītu citus vienumus"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Notiek ieteikumu ielāde"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Aizvērt multivides sesiju"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Atsākt"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktīva, pārbaudiet lietotni"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Radās kļūda. Mēģina vēlreiz…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Ierīce ir noņemta."</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Netika atrasta"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Vadīkla nav pieejama"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Nevarēja piekļūt ierīcei “<xliff:g id="DEVICE">%1$s</xliff:g>”. Lietotnē <xliff:g id="APPLICATION">%2$s</xliff:g> pārbaudiet, vai vadīkla joprojām ir pieejama un vai nav mainīti lietotnes iestatījumi."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Atvērt lietotni"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Nevar ielādēt statusu."</string>
<string name="controls_error_failed" msgid="960228639198558525">"Radās kļūda. Mēģiniet vēlreiz."</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Sākta"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 0361eed..522cebd 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Премести горе десно"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Премести долу лево"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Премести долу десно"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Отфрли"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Не прикажувај го разговорот во балончиња"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Разговор во балончиња"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Новите разговори ќе се појавуваат како лебдечки икони или балончиња. Допрете за отворање на балончето. Повлечете за да го преместите."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Повлечете за да видите повеќе"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Се вчитуваат препораки"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Затвори ја аудиовизуелнава сесија"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Продолжи"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивна, провери апликација"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Грешка, повторен обид…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Уредот е отстранет"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Не е најдено"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Контролата не е достапна"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Не може да се пристапи до <xliff:g id="DEVICE">%1$s</xliff:g>. Проверете ја апликацијата <xliff:g id="APPLICATION">%2$s</xliff:g> за да се осигурите дека контролата е сè уште достапна и дека поставките за апликацијата не се сменети."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Отвори ја апликација"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Не може да се вчита статусот"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Грешка, обидете се повторно"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Во тек"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 5c80eb3..03e826f 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"മുകളിൽ വലതുഭാഗത്തേക്ക് നീക്കുക"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"ചുവടെ ഇടതുഭാഗത്തേക്ക് നീക്കുക"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"ചുവടെ വലതുഭാഗത്തേക്ക് നീക്കുക"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"ഡിസ്മിസ് ചെയ്യുക"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"സംഭാഷണം ബബിൾ ചെയ്യരുത്"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"ബബിളുകൾ ഉപയോഗിച്ച് ചാറ്റ് ചെയ്യുക"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"പുതിയ സംഭാഷണങ്ങൾ ഫ്ലോട്ടിംഗ് ഐക്കണുകളോ ബബിളുകളോ ആയി ദൃശ്യമാവുന്നു. ബബിൾ തുറക്കാൻ ടാപ്പ് ചെയ്യു. ഇത് നീക്കാൻ വലിച്ചിടുക."</string>
@@ -1065,9 +1066,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"കൂടുതൽ കാണാൻ സ്വൈപ്പ് ചെയ്യുക"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"നിർദ്ദേശങ്ങൾ ലോഡ് ചെയ്യുന്നു"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"ഈ മീഡിയ സെഷൻ അടയ്ക്കുക"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"പുനരാരംഭിക്കുക"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"നിഷ്ക്രിയം, ആപ്പ് പരിശോധിക്കൂ"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"പിശക്, വീണ്ടും ശ്രമിക്കുന്നു…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"ഉപകരണം നീക്കം ചെയ്തു"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"കണ്ടെത്തിയില്ല"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"നിയന്ത്രണം ലഭ്യമല്ല"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> ആക്സസ് ചെയ്യാനായില്ല. നിയന്ത്രണം ഇപ്പോഴും ലഭ്യമാണെന്നും ആപ്പ് ക്രമീകരണം മാറ്റിയിട്ടില്ലെന്നും ഉറപ്പാക്കാൻ <xliff:g id="APPLICATION">%2$s</xliff:g> ആപ്പ് പരിശോധിക്കുക."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"ആപ്പ് തുറക്കുക"</string>
<string name="controls_error_generic" msgid="352500456918362905">"നില ലോഡ് ചെയ്യാനാകുന്നില്ല"</string>
<string name="controls_error_failed" msgid="960228639198558525">"പിശക്, വീണ്ടും ശ്രമിക്കുക"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"പുരോഗതിയിലാണ്"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index f04df52..9a15e98 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Баруун дээш зөөх"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Зүүн доош зөөх"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Баруун доош зөөх"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Үл хэрэгсэх"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Харилцан яриаг бүү бөмбөлөг болго"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Бөмбөлөг ашиглан чатлаарай"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Шинэ харилцан яриа нь хөвөгч дүрс тэмдэг эсвэл бөмбөлөг хэлбэрээр харагддаг. Бөмбөлгийг нээхийн тулд товшино уу. Түүнийг зөөхийн тулд чирнэ үү."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Илүү ихийг харахын тулд шударна уу"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Зөвлөмжүүдийг ачаалж байна"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Медианы энэ харилцан үйлдлийг хаах"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Үргэлжлүүлэх"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Идэвхгүй байна, аппыг шалгана уу"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Алдаа, дахин оролдож байна…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Төхөөрөмжийг хассан"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Олдсонгүй"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Хяналт боломжгүй байна"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g>-д хандаж чадсангүй. Хяналт боломжтой хэвээр байгаа бөгөөд аппын тохиргоог өөрчлөөгүй эсэхийг нягтлахын тулд <xliff:g id="APPLICATION">%2$s</xliff:g> аппыг шалгана уу."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Аппыг нээх"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Статус ачаалах боломжгүй"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Алдаа гарав, дахин оролдоно уу"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Үргэлжилж байна"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 8994141..cbc50b9 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"वर उजवीकडे हलवा"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"तळाशी डावीकडे हलवा"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"तळाशी उजवीकडे हलवा"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"डिसमिस करा"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"संभाषणाला बबल करू नका"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"बबल वापरून चॅट करा"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"नवीन संभाषणे फ्लोटिंग आयकन किंवा बबल म्हणून दिसतात. बबल उघडण्यासाठी टॅप करा. हे हलवण्यासाठी ड्रॅग करा."</string>
@@ -1065,9 +1066,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"अधिक पाहण्यासाठी स्वाइप करा"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"शिफारशी लोड करत आहे"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"हे मीडिया सेशन बंद करा"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"पुन्हा सुरू करा"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय, ॲप तपासा"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"एरर, पुन्हा प्रयत्न करत आहे…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"डिव्हाइस काढून टाकले आहे"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"आढळले नाही"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"नियंत्रण उपलब्ध नाही"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> अॅक्सेस करता आले नाही. नियंत्रण अजूनही उपलब्ध असल्याची आणि ॲपची सेटिंग्ज बदलली नसल्याची खात्री करण्यासाठी <xliff:g id="APPLICATION">%2$s</xliff:g> ॲप तपासा."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"अॅप उघडा"</string>
<string name="controls_error_generic" msgid="352500456918362905">"स्थिती लोड करू शकत नाही"</string>
<string name="controls_error_failed" msgid="960228639198558525">"एरर, पुन्हा प्रयत्न करा"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"प्रगतीपथावर आहे"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index a251c3d..f89d5a0 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Alihkan ke atas sebelah kanan"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Alihkan ke bawah sebelah kiri"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Alihkan ke bawah sebelah kanan"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Ketepikan"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Jangan jadikan perbualan dalam bentuk gelembung"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Bersembang menggunakan gelembung"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Perbualan baharu muncul sebagai ikon terapung atau gelembung. Ketik untuk membuka gelembung. Seret untuk mengalihkan gelembung tersebut."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Leret untuk melihat selanjutnya"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Memuatkan cadangan"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Tutup sesi media ini"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Sambung semula"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Tidak aktif, semak apl"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Ralat, mencuba semula…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Peranti dialih keluar"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Tidak ditemui"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Kawalan tidak tersedia"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Tidak dapat mengakses <xliff:g id="DEVICE">%1$s</xliff:g>. Periksa apl <xliff:g id="APPLICATION">%2$s</xliff:g> untuk memastikan kawalan masih tersedia dan tetapan apl tidak berubah."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Buka apl"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Tidak dapat memuatkan status"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Ralat, cuba lagi"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Sedang berlangsung"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 810388d..dc70e80 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"ညာဘက်ထိပ်သို့ ရွှေ့ပါ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"ဘယ်အောက်ခြေသို့ ရွှေ့ရန်"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"ညာအောက်ခြေသို့ ရွှေ့ပါ"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"ပယ်ရန်"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"စကားဝိုင်းကို ပူဖောင်းကွက် မပြုလုပ်ပါနှင့်"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"ပူဖောင်းကွက် သုံး၍ ချတ်လုပ်ခြင်း"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"စကားဝိုင်းအသစ်များကို မျောနေသည့် သင်္ကေတများ သို့မဟုတ် ပူဖောင်းကွက်များအဖြစ် မြင်ရပါမည်။ ပူဖောင်းကွက်ကိုဖွင့်ရန် တို့ပါ။ ရွှေ့ရန် ၎င်းကို ဖိဆွဲပါ။"</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"ပိုမိုကြည့်ရှုရန် ပွတ်ဆွဲပါ"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"အကြံပြုချက်များ ဖွင့်နေသည်"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"ဤမီဒီယာစက်ရှင်ကို ပိတ်ပါ"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"ဆက်လုပ်ရန်"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ရပ်နေသည်၊ အက်ပ်ကို စစ်ဆေးပါ"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"မှားသွားသည်၊ ပြန်စမ်းနေသည်…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"စက်ကို ဖယ်ရှားထားသည်"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"မတွေ့ပါ"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"ထိန်းချုပ်၍ မရတော့ပါ"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> အသုံးပြု၍ မရပါ။ ထိန်းချုပ်၍ ရသေးကြောင်းနှင့် အက်ပ်ဆက်တင်များ ပြောင်းမထားကြောင်း သေချာစေရန် <xliff:g id="APPLICATION">%2$s</xliff:g> အက်ပ်ကို စစ်ဆေးပါ။"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"အက်ပ်ဖွင့်ရန်"</string>
<string name="controls_error_generic" msgid="352500456918362905">"အခြေအနေကို ဖွင့်၍မရပါ"</string>
<string name="controls_error_failed" msgid="960228639198558525">"မှားသွားသည်၊ ပြန်စမ်းကြည့်ပါ"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"ဆောင်ရွက်နေသည်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index b208cf2..53806a7 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -1002,10 +1002,11 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Flytt til øverst til høyre"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Flytt til nederst til venstre"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Flytt til nederst til høyre"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Avvis"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Ikke vis samtaler i bobler"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chat med bobler"</string>
- <string name="bubbles_user_education_description" msgid="1160281719576715211">"Nye samtaler vises som flytende ikoner, eller bobler. Trykk for å åpne bobler. Dra for å flytte dem."</string>
+ <string name="bubbles_user_education_description" msgid="1160281719576715211">"Nye samtaler vises som flytende ikoner eller bobler. Trykk for å åpne bobler. Dra for å flytte dem."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Kontrollér bobler når som helst"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Trykk på Administrer for å slå av bobler for denne appen"</string>
<string name="bubbles_user_education_got_it" msgid="8282812431953161143">"Greit"</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Sveip for å se flere"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Laster inn anbefalinger"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Lukk denne medieøkten"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Gjenoppta"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv. Sjekk appen"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Feil. Prøver igjen …"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Enheten er fjernet"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Ikke funnet"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrollen er utilgjengelig"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Fikk ikke tilgang til <xliff:g id="DEVICE">%1$s</xliff:g>. Sjekk <xliff:g id="APPLICATION">%2$s</xliff:g>-appen for å sjekke at kontrollen fremdeles er tilgjengelig, og at appinnstillingene ikke er endret."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Åpne appen"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Kan ikke laste inn status"</string>
<string name="controls_error_failed" msgid="960228639198558525">"En feil oppsto. Prøv på nytt"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Pågår"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index abfb4c8..19cf233 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"सिरानमा दायाँतिर सार्नुहोस्"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"पुछारमा बायाँतिर सार्नुहोस्"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"पुछारमा दायाँतिर सार्नुहोस्"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"हटाउनुहोस्"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"वार्तालाप बबलको रूपमा नदेखाइयोस्"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"बबलहरू प्रयोग गरी कुराकानी गर्नुहोस्"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"नयाँ वार्तालापहरू तैरने आइकन वा बबलका रूपमा देखिन्छन्। बबल खोल्न ट्याप गर्नुहोस्। बबल सार्न सो बबललाई ड्र्याग गर्नुहोस्।"</string>
@@ -1065,9 +1066,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"थप हेर्न स्वाइप गर्नुहोस्"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"सिफारिसहरू लोड गर्दै"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"यो मिडिया सत्र बन्द गर्नुहोस्"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"सुचारु गर्नुहोस्"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"निष्क्रिय छ, एप जाँच गर्नु…"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"त्रुटि भयो, फेरि प्रयास गर्दै…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"यन्त्र हटाइयो"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"फेला परेन"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"नियन्त्रण सुविधा उपलब्ध छैन"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> माथि पहुँच राख्न सकिएन। यो नियन्त्रण सुविधा अझै पनि उपलब्ध छ र <xliff:g id="APPLICATION">%2$s</xliff:g> एपका सेटिङ परिवर्तन गरिएका छैनन् भन्ने कुरा सुनिश्चित गर्न यो एप जाँच्नुहोस्।"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"एप खोल्नुहोस्"</string>
<string name="controls_error_generic" msgid="352500456918362905">"वस्तुस्थिति लोड गर्न सकिएन"</string>
<string name="controls_error_failed" msgid="960228639198558525">"त्रुटि भयो, फेरि प्रयास गर्नु…"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"कार्य हुँदै छ"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index f578c2d..21e66ab 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Naar rechtsboven verplaatsen"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Naar linksonder verplaatsen"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Naar rechtsonder verplaatsen"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Sluiten"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Gesprekken niet in bubbels weergeven"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chatten met bubbels"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Nieuwe gesprekken worden weergegeven als zwevende iconen of \'bubbels\'. Tik om een bubbel te openen. Sleep om de bubbel te verplaatsen."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Swipe om meer te zien"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Aanbevelingen laden"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Deze mediasessie sluiten"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Hervatten"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactief, check de app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Fout. Opnieuw proberen…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Apparaat verwijderd"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Niet gevonden"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Beheeroptie niet beschikbaar"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Kan geen toegang krijgen tot <xliff:g id="DEVICE">%1$s</xliff:g>. Check de <xliff:g id="APPLICATION">%2$s</xliff:g>-app om na te gaan of de beheeroptie nog steeds beschikbaar is en of de app-instellingen niet zijn gewijzigd."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"App openen"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Kan status niet laden"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Fout, probeer het opnieuw"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Bezig"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 27a04dd..f575f98 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"ଉପର-ଡାହାଣକୁ ନିଅନ୍ତୁ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"ତଳ ବାମକୁ ନିଅନ୍ତୁ"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"ତଳ ଡାହାଣକୁ ନିଅନ୍ତୁ"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"ଖାରଜ କରନ୍ତୁ"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"ବାର୍ତ୍ତାଳାପକୁ ବବଲ୍ କରନ୍ତୁ ନାହିଁ"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"ବବଲଗୁଡ଼ିକୁ ବ୍ୟବହାର କରି ଚାଟ୍ କରନ୍ତୁ"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"ନୂଆ ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ ଫ୍ଲୋଟିଂ ଆଇକନ୍ କିମ୍ବା ବବଲ୍ ଭାବେ ଦେଖାଯିବ। ବବଲ୍ ଖୋଲିବାକୁ ଟାପ୍ କରନ୍ତୁ। ଏହାକୁ ମୁଭ୍ କରିବାକୁ ଟାଣନ୍ତୁ।"</string>
@@ -1065,9 +1066,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"ଅଧିକ ଦେଖିବାକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ସୁପାରିଶଗୁଡ଼ିକ ଲୋଡ୍ କରାଯାଉଛି"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"ଏହି ମିଡିଆ ସେସନ୍ ବନ୍ଦ କରନ୍ତୁ"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"ପୁଣି ଆରମ୍ଭ କରନ୍ତୁ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ନିଷ୍କ୍ରିୟ ଅଛି, ଆପ ଯାଞ୍ଚ କରନ୍ତୁ"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"ତ୍ରୁଟି, ପୁଣି ଚେଷ୍ଟା କରୁଛି…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"ଡିଭାଇସ୍ କାଢ଼ି ଦିଆଯାଇଛି"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"ମିଳୁ ନାହିଁ"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"ନିୟନ୍ତ୍ରଣ ଉପଲବ୍ଧ ନାହିଁ"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g>କୁ ଆକ୍ସେସ୍ କରିହେଲା ନାହିଁ। ନିୟନ୍ତ୍ରଣ ଏବେ ବି ଉପଲବ୍ଧ ଅଛି ଏବଂ ଆପ୍ ସେଟିଂସ୍ ବଦଳାଯାଇ ନାହିଁ ବୋଲି ସୁନିଶ୍ଚିତ କରିବାକୁ <xliff:g id="APPLICATION">%2$s</xliff:g> ଆପ୍ ଯାଞ୍ଚ କରନ୍ତୁ।"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"ଆପ୍ ଖୋଲନ୍ତୁ"</string>
<string name="controls_error_generic" msgid="352500456918362905">"ସ୍ଥିତି ଲୋଡ୍ କରାଯାଇପାରିବ ନାହିଁ"</string>
<string name="controls_error_failed" msgid="960228639198558525">"ତ୍ରୁଟି ହୋଇଛି, ପୁଣି ଚେଷ୍ଟା କର"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"ପ୍ରଗତିରେ ଅଛି"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index b8bf05b..3389a18 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -273,7 +273,7 @@
<string name="accessibility_quick_settings_airplane_on" msgid="8106176561295294255">"ਏਅਰਪਲੇਨ ਮੋਡ ਚਾਲੂ।"</string>
<string name="accessibility_quick_settings_airplane_changed_off" msgid="8880183481476943754">"ਏਅਰਪਲੇਨ ਮੋਡ ਬੰਦ ਹੈ।"</string>
<string name="accessibility_quick_settings_airplane_changed_on" msgid="6327378061894076288">"ਏਅਰਪਲੇਨ ਮੋਡ ਚਾਲੂ ਹੋਇਆ"</string>
- <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"ਸੰਪੂਰਨ ਖਾਮੋਸ਼ੀ"</string>
+ <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"ਪੂਰਾ ਸ਼ਾਂਤ"</string>
<string name="accessibility_quick_settings_dnd_alarms_on" msgid="3375848309132140014">"ਸਿਰਫ਼ ਅਲਾਰਮ"</string>
<string name="accessibility_quick_settings_dnd" msgid="2415967452264206047">"ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ।"</string>
<string name="accessibility_quick_settings_dnd_changed_off" msgid="1457150026842505799">"\'ਪਰੇਸ਼ਾਨ ਨਾ ਕਰੋ\' ਨੂੰ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string>
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"ਉੱਪਰ ਵੱਲ ਸੱਜੇ ਲਿਜਾਓ"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"ਹੇਠਾਂ ਵੱਲ ਖੱਬੇ ਲਿਜਾਓ"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"ਹੇਠਾਂ ਵੱਲ ਸੱਜੇ ਲਿਜਾਓ"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"ਖਾਰਜ ਕਰੋ"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"ਗੱਲਬਾਤ \'ਤੇ ਬਬਲ ਨਾ ਲਾਓ"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"ਬਬਲ ਵਰਤਦੇ ਹੋਏ ਚੈਟ ਕਰੋ"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"ਨਵੀਆਂ ਗੱਲਾਂਬਾਤਾਂ ਫਲੋਟਿੰਗ ਪ੍ਰਤੀਕਾਂ ਜਾਂ ਬਬਲ ਦੇ ਰੂਪ ਵਿੱਚ ਦਿਸਦੀਆਂ ਹਨ। ਬਬਲ ਨੂੰ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ। ਇਸਨੂੰ ਲਿਜਾਣ ਲਈ ਘਸੀਟੋ।"</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"ਹੋਰ ਦੇਖਣ ਲਈ ਸਵਾਈਪ ਕਰੋ"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"ਸਿਫ਼ਾਰਸ਼ਾਂ ਲੋਡ ਹੋ ਰਹੀਆਂ ਹਨ"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"ਇਸ ਮੀਡੀਆ ਸੈਸ਼ਨ ਨੂੰ ਬੰਦ ਕਰੋ"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ਅਕਿਰਿਆਸ਼ੀਲ, ਐਪ ਦੀ ਜਾਂਚ ਕਰੋ"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"ਗੜਬੜ, ਮੁੜ ਕੋਸ਼ਿਸ਼ ਹੋ ਰਹੀ ਹੈ…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"ਡੀਵਾਈਸ ਹਟਾਇਆ ਗਿਆ"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"ਨਹੀਂ ਮਿਲਿਆ"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"ਕੰਟਰੋਲ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> ਤੱਕ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ। ਇਹ ਪੱਕਾ ਕਰਨ ਲਈ <xliff:g id="APPLICATION">%2$s</xliff:g> ਐਪ ਦੀ ਜਾਂਚ ਕਰੋ ਕਿ ਕੰਟਰੋਲ ਹਾਲੇ ਵੀ ਉਪਲਬਧ ਹੈ ਅਤੇ ਐਪ ਸੈਟਿੰਗ ਬਦਲੀ ਨਹੀਂ ਹੈ।"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"ਐਪ ਖੋਲ੍ਹੋ"</string>
<string name="controls_error_generic" msgid="352500456918362905">"ਸਥਿਤੀ ਲੋਡ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ"</string>
<string name="controls_error_failed" msgid="960228639198558525">"ਗੜਬੜ, ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"ਜਾਰੀ ਹੈ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 8b56f8d..e85b76f 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -1012,7 +1012,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Przenieś w prawy górny róg"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Przenieś w lewy dolny róg"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Przenieś w prawy dolny róg"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Zamknij"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nie wyświetlaj rozmowy jako dymku"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Czatuj, korzystając z dymków"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Nowe rozmowy będą wyświetlane jako pływające ikony lub dymki. Kliknij, by otworzyć dymek. Przeciągnij, by go przenieść."</string>
@@ -1074,9 +1075,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Przesuń palcem, by zobaczyć więcej"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Wczytuję rekomendacje"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Zamknij tę sesję multimediów"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Wznów"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nieaktywny, sprawdź aplikację"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Błąd, próbuję jeszcze raz…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Usunięto urządzenie"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Nie znaleziono"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Element jest niedostępny"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Nie udało się połączyć z urządzeniem: <xliff:g id="DEVICE">%1$s</xliff:g>. Sprawdź aplikację <xliff:g id="APPLICATION">%2$s</xliff:g>, aby upewnić się, że element sterujący jest wciąż dostępny i ustawienia aplikacji się nie zmieniły."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Otwórz aplikację"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Nie udało się wczytać stanu"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Błąd, spróbuj ponownie"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"W toku"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 5a2005e..2259c30 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Mover para canto superior direito"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Mover para canto inferior esquerdo"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Mover para canto inferior direito"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Dispensar"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Não criar balões de conversa"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Converse usando balões"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Novas conversas aparecerão como ícones flutuantes, ou balões. Toque para abrir o balão. Arraste para movê-lo."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Deslize para ver mais"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregando recomendações"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Encerrar esta sessão de mídia"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erro. Tentando novamente…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Dispositivo removido"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"O controle está indisponível"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Não foi possível acessar <xliff:g id="DEVICE">%1$s</xliff:g>. Verifique o app <xliff:g id="APPLICATION">%2$s</xliff:g> para garantir que o controle ainda esteja disponível e as configurações não tenham sido modificadas."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Abrir app"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Falha ao carregar o status"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Erro. Tente novamente"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Em andamento"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index dec586e..d90b8b2 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Mover parte superior direita"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Mover p/ parte infer. esquerda"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Mover parte inferior direita"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Ignorar"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Não apresentar a conversa em balões"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Converse no chat através de balões"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"As novas conversas aparecem como ícones flutuantes ou balões. Toque para abrir o balão. Arraste para o mover."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Deslize rapidamente para ver mais."</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"A carregar recomendações…"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Fechar esta sessão multimédia"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativa. Consulte a app."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erro. A tentar novamente…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Dispositivo removido."</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado."</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"O controlo está indisponível"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Não foi possível aceder a <xliff:g id="DEVICE">%1$s</xliff:g>. Verifique a app <xliff:g id="APPLICATION">%2$s</xliff:g> para se certificar de que o controlo ainda está disponível e que as definições da mesma não foram alteradas."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Abrir app"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Impossível carregar o estado."</string>
<string name="controls_error_failed" msgid="960228639198558525">"Erro. Tente novamente."</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Em curso"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 5a2005e..2259c30 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Mover para canto superior direito"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Mover para canto inferior esquerdo"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Mover para canto inferior direito"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Dispensar"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Não criar balões de conversa"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Converse usando balões"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Novas conversas aparecerão como ícones flutuantes, ou balões. Toque para abrir o balão. Arraste para movê-lo."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Deslize para ver mais"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Carregando recomendações"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Encerrar esta sessão de mídia"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Retomar"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inativo, verifique o app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Erro. Tentando novamente…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Dispositivo removido"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Não encontrado"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"O controle está indisponível"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Não foi possível acessar <xliff:g id="DEVICE">%1$s</xliff:g>. Verifique o app <xliff:g id="APPLICATION">%2$s</xliff:g> para garantir que o controle ainda esteja disponível e as configurações não tenham sido modificadas."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Abrir app"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Falha ao carregar o status"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Erro. Tente novamente"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Em andamento"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index ee844d0..c90c04c 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -1007,7 +1007,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Mutați în dreapta sus"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Mutați în stânga jos"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Mutați în dreapta jos"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Închideți"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nu afișați conversația în balon"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Discutați pe chat folosind baloanele"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Conversațiile noi apar ca pictograme flotante sau baloane. Atingeți pentru a deschide balonul. Trageți pentru a-l muta."</string>
@@ -1068,9 +1069,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Glisați pentru a vedea mai multe"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Se încarcă recomandările"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Închideți această sesiune media"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Reia"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inactiv, verificați aplicația"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Eroare, se încearcă din nou…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Dispozitivul a fost eliminat"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Nu s-a găsit"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Comanda este indisponibilă"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Nu s-a putut accesa <xliff:g id="DEVICE">%1$s</xliff:g>. Accesați aplicația <xliff:g id="APPLICATION">%2$s</xliff:g> pentru a vă asigura de disponibilitatea comenzii și că setările aplicației nu s-au schimbat."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Deschideți aplicația"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Starea nu se poate încărca"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Eroare, încercați din nou"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"În curs"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 902d948..35f4b74 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -1012,7 +1012,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Перенести в правый верхний угол"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Перенести в левый нижний угол"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Перенести в правый нижний угол"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Закрыть"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Не показывать всплывающие чаты для разговоров"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Всплывающие чаты для разговоров"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Новые разговоры будут появляться в виде плавающих значков, или всплывающих чатов. Чтобы открыть чат, нажмите на него, а чтобы переместить – перетащите."</string>
@@ -1074,9 +1075,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Проведите по экрану, чтобы увидеть больше"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Загрузка рекомендаций…"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Закрыть этот мультимедийный сеанс"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Возобновить"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Нет ответа. Проверьте приложение."</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Ошибка. Повторная попытка…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Устройство удалено."</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Не найдено."</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Управление недоступно"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Нет доступа к устройству (<xliff:g id="DEVICE">%1$s</xliff:g>). Проверьте, доступно ли управление в приложении \"<xliff:g id="APPLICATION">%2$s</xliff:g>\" и не изменились ли настройки этого приложения."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Открыть приложение"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Не удалось загрузить статус."</string>
<string name="controls_error_failed" msgid="960228639198558525">"Ошибка. Повторите попытку."</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Выполняется"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index c49843c..be88cba 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"ඉහළ දකුණට ගෙන යන්න"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"පහළ වමට ගෙන යන්න"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"පහළ දකුණට ගෙන යන්න"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"ඉවතලන්න"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"සංවාදය බුබුලු නොදමන්න"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"බුබුලු භාවිතයෙන් කතාබහ කරන්න"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"නව සංවාද පාවෙන අයිකන හෝ බුබුලු ලෙස දිස් වේ. බුබුල විවෘත කිරීමට තට්ටු කරන්න. එය ගෙන යාමට අදින්න."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"තව බැලීමට ස්වයිප් කරන්න"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"නිර්දේශ පූරණය කරමින්"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"මෙම මාධ්ය සැසිය වසන්න"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"නැවත පටන් ගන්න"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"අක්රියයි, යෙදුම පරීක්ෂා කරන්න"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"දෝෂයකි, නැවත උත්සාහ කරමින්…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"උපාංගය ඉවත් කර ඇත"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"හමු නොවිණි"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"පාලනය ලබා ගත නොහැකිය"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> වෙත ප්රවේශ විය නොහැකි විය. පාලනය තිබෙන බව සහ යෙදුම් සැකසීම් වෙනස් වී ඇති බව සහතික කර ගැනීමට <xliff:g id="APPLICATION">%2$s</xliff:g> යෙදුම පරීක්ෂා කරන්න."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"යෙදුම විවෘත කරන්න"</string>
<string name="controls_error_generic" msgid="352500456918362905">"තත්ත්වය පූරණය කළ නොහැකිය"</string>
<string name="controls_error_failed" msgid="960228639198558525">"දෝෂයකි, නැවත උත්සාහ කරන්න"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"ප්රගතියේ පවතී"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 920fdd1..e0ba13d 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -1012,7 +1012,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Presunúť doprava nahor"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Presunúť doľava nadol"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Presunúť doprava nadol"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Zavrieť"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nezobrazovať konverzáciu ako bublinu"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Čet pomocou bublín"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Nové konverzácie sa zobrazujú ako plávajúce ikony či bubliny. Bublinu otvoríte klepnutím. Premiestnite ju presunutím."</string>
@@ -1074,9 +1075,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Potiahnutím zobrazíte ďalšie položky"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Načítavajú sa odporúčania"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Zavrieť túto reláciu média"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Pokračovať"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktívne, preverte aplikáciu"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Chyba, skúša sa znova…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Zariadenie je odstránené"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Nenájdené"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Ovládanie nie je k dispozícii"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Nepodarilo sa získať prístup k zariadeniu <xliff:g id="DEVICE">%1$s</xliff:g>. V aplikácii <xliff:g id="APPLICATION">%2$s</xliff:g> skontrolujte, či je ovládanie stále k dispozícii a či sa nezmenili nastavenia."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Otvoriť aplikáciu"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Stav sa nepodarilo načítať"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Chyba, skúste to znova"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Prebieha"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 0b6d3a7..7066e8d 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -1012,7 +1012,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Premakni zgoraj desno"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Premakni spodaj levo"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Premakni spodaj desno"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Opusti"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Pogovora ne prikaži v oblačku"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Klepet z oblački"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Novi pogovori so prikazani kot lebdeče ikone ali oblački. Če želite odpreti oblaček, se ga dotaknite. Če ga želite premakniti, ga povlecite."</string>
@@ -1074,9 +1075,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Če si želite ogledati več, povlecite"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Nalaganje priporočil"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Zapri to sejo predstavnosti"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Nadaljuj"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Neaktivno, poglejte aplikacijo"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Napaka, vnovični poskus …"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Naprava je bila odstranjena"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Ni mogoče najti"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrolnik ni na voljo"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Ni bilo mogoče dostopiti do: <xliff:g id="DEVICE">%1$s</xliff:g>. Preverite aplikacijo <xliff:g id="APPLICATION">%2$s</xliff:g> in se prepričajte, da je kontrolnik še vedno na voljo ter da se nastavitve aplikacije niso spremenile."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Odpri aplikacijo"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Stanja ni mogoče naložiti"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Napaka, poskusite znova"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"V teku"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index a514750..a23a85b 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Lëviz lart djathtas"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Zhvendos poshtë majtas"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Lëvize poshtë djathtas"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Hiq"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Mos e vendos bisedën në flluskë"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Bisedo duke përdorur flluskat"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Bisedat e reja shfaqen si ikona pluskuese ose flluska. Trokit për të hapur flluskën. Zvarrit për ta zhvendosur."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Rrëshqit shpejt për të shikuar më shumë"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Po ngarkon rekomandimet"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Mbyll këtë sesion të medias"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Vazhdo"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Joaktive, kontrollo aplikacionin"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Gabim, po provohet përsëri"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Pajisja u hoq"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Nuk u gjet"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrolli është i padisponueshëm"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Nuk mundi të qasej te <xliff:g id="DEVICE">%1$s</xliff:g>. Kontrollo aplikacionin <xliff:g id="APPLICATION">%2$s</xliff:g> për t\'u siguruar që kontrolli të jetë ende i disponueshëm dhe që cilësimet e aplikacionit të mos kenë ndryshuar."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Hap aplikacionin"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Statusi nuk mund të ngarkohet"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Gabim, provo sërish"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Në vazhdim"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 7855ec1..fde6413 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -1007,9 +1007,10 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Премести горе десно"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Премести доле лево"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Премести доле десно"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Одбаци"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Не користи облачиће за конверзацију"</string>
- <string name="bubbles_user_education_title" msgid="5547017089271445797">"Ћаскајте помоћу облачића"</string>
+ <string name="bubbles_user_education_title" msgid="5547017089271445797">"Ћаскајте у облачићима"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Нове конверзације се приказују као плутајуће иконе или облачићи. Додирните да бисте отворили облачић. Превуците да бисте га преместили."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Контролишите облачиће у било ком тренутку"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Додирните Управљајте да бисте искључили облачиће из ове апликације"</string>
@@ -1068,9 +1069,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Превуците да бисте видели још"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Учитавају се препоруке"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Затворите ову сесију медија"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Настави"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно. Видите апликацију"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Грешка, покушава се поново…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Уређај је уклоњен"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Није пронађено"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Контрола није доступна"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Приступање уређају <xliff:g id="DEVICE">%1$s</xliff:g> није успело. Погледајте апликацију <xliff:g id="APPLICATION">%2$s</xliff:g> да бисте се уверили да је контрола још увек доступна и да се подешавања апликације нису променила."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Отвори апликацију"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Учитавање статуса није успело"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Грешка. Пробајте поново"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"У току"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index e6fb28e..af3839b 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Flytta högst upp till höger"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Flytta längst ned till vänster"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Flytta längst ned till höger"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Stäng"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Visa inte konversationen i bubblor"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Chatta med bubblor"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Nya konversationer visas som flytande ikoner, så kallade bubblor. Tryck på bubblan om du vill öppna den. Dra den om du vill flytta den."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Svep om du vill se mer"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Rekommendationer läses in"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Stäng den här sessionen"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Återuppta"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Inaktiv, kolla appen"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Fel, försöker igen …"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Enheten har tagits bort"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Hittades inte"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Styrning är inte tillgänglig"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Det gick inte att komma åt <xliff:g id="DEVICE">%1$s</xliff:g>. Kontrollera att enheten fortfarande är tillgänglig för styrning och att appinställningarna inte har ändrats i <xliff:g id="APPLICATION">%2$s</xliff:g>-appen."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Öppna appen"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Ingen status lästes in"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Fel, försök igen"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Pågår"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index c7962f9..f5ec81bf 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Sogeza juu kulia"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Sogeza chini kushoto"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Sogeza chini kulia"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Ondoa"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Usiweke viputo kwenye mazungumzo"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Piga gumzo ukitumia viputo"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Mazungumzo mapya huonekena kama aikoni au viputo vinavyoelea. Gusa ili ufungue kiputo. Buruta ili ukisogeze."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Telezesha kidole ili uone zaidi"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Inapakia mapendekezo"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Funga kipindi hiki cha maudhui"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Endelea"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Haitumiki, angalia programu"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Hitilafu, inajaribu tena…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Kifaa kimeondolewa"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Hakipatikani"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Kidhibiti hakipatikani"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Imeshindwa kufikia <xliff:g id="DEVICE">%1$s</xliff:g>. Angalia programu ya <xliff:g id="APPLICATION">%2$s</xliff:g> ili uhakikishe kuwa bado kidhibiti kipo na kuwa mipangilio ya programu haijabadilika."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Fungua programu"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Imeshindwa kupakia hali"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Hitilafu, jaribu tena"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Inaendelea"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index edd8bde..4a32ecf 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"மேலே வலப்புறமாக நகர்த்து"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"கீழே இடப்புறமாக நகர்த்து"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"கீழே வலதுபுறமாக நகர்த்து"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"மூடுக"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"உரையாடலைக் குமிழாக்காதே"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"குமிழ்களைப் பயன்படுத்தி அரட்டையடியுங்கள்"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"புதிய உரையாடல்கள் மிதக்கும் ஐகான்களாகவோ குமிழ்களாகவோ தோன்றும். குமிழைத் திறக்க தட்டவும். நகர்த்த இழுக்கவும்."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"மேலும் பார்க்க ஸ்வைப் செய்யவும்"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"பரிந்துரைகளை ஏற்றுகிறது"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"இந்த மீடியா அமர்வை மூடுக"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"தொடர்க"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"செயலில் இல்லை , சரிபார்க்கவும்"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"பிழை, மீண்டும் முயல்கிறது…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"சாதனம் அகற்றப்பட்டது"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"இல்லை"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"கட்டுப்பாடு இல்லை"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> சாதனத்தை அணுக இயலவில்லை. இப்போதும் கட்டுப்பாடு உள்ளது என்பதையும் ஆப்ஸ் அமைப்புகள் மாறவில்லை என்பதையும் உறுதிப்படுத்த <xliff:g id="APPLICATION">%2$s</xliff:g> ஆப்ஸைப் பார்க்கவும்."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"ஆப்ஸைத் திற"</string>
<string name="controls_error_generic" msgid="352500456918362905">"நிலையைக் காட்ட முடியவில்லை"</string>
<string name="controls_error_failed" msgid="960228639198558525">"பிழை, மீண்டும் முயலவும்"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"செயல்பாட்டிலுள்ளது"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index a08d0d4..73754a2 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"ఎగువ కుడివైపునకు జరుపు"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"దిగువ ఎడమవైపునకు తరలించు"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"దిగవు కుడివైపునకు జరుపు"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"విస్మరించు"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"సంభాషణను బబుల్ చేయవద్దు"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"బబుల్స్ను ఉపయోగించి చాట్ చేయండి"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"కొత్త సంభాషణలు తేలియాడే చిహ్నాలుగా లేదా బబుల్స్ లాగా కనిపిస్తాయి. బబుల్ని తెరవడానికి నొక్కండి. తరలించడానికి లాగండి."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"మరిన్నింటిని చూడటం కోసం స్వైప్ చేయండి"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"సిఫార్సులు లోడ్ అవుతున్నాయి"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"ఈ మీడియా సెషన్ని మూసివేయండి"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"కొనసాగించండి"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ఇన్యాక్టివ్, యాప్ చెక్ చేయండి"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"లోపం, మళ్లీ ప్రయత్నిస్తోంది..."</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"పరికరం తీసివేయబడింది"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"కనుగొనబడలేదు"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"కంట్రోల్ అందుబాటులో లేదు"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g>ను యాక్సెస్ చేయడం సాధ్యపడలేదు. <xliff:g id="APPLICATION">%2$s</xliff:g> యాప్ను తనిఖీ చేసి, కంట్రోల్ ఇప్పటికీ అందుబాటులో ఉందని, యాప్ సెట్టింగ్లు మారలేదని నిర్ధారించుకోండి."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"యాప్ను తెరువు"</string>
<string name="controls_error_generic" msgid="352500456918362905">"స్థితిని లోడ్ చేయడం సాధ్యపడదు"</string>
<string name="controls_error_failed" msgid="960228639198558525">"ఎర్రర్, మళ్లీ ప్రయత్నించండి"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"పురోగతిలో ఉంది"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 5638f2a51..d61533d 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"ย้ายไปด้านขวาบน"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"ย้ายไปด้านซ้ายล่าง"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"ย้ายไปด้านขาวล่าง"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"ปิด"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"ไม่ต้องแสดงการสนทนาเป็นบับเบิล"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"แชทโดยใช้บับเบิล"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"การสนทนาใหม่ๆ จะปรากฏเป็นไอคอนแบบลอยหรือบับเบิล แตะเพื่อเปิดบับเบิล ลากเพื่อย้ายที่"</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"เลื่อนเพื่อดูเพิ่มเติม"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"กำลังโหลดคำแนะนำ"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"ปิดเซสชันสื่อนี้"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"เล่นต่อ"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"ไม่มีการใช้งาน โปรดตรวจสอบแอป"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"มีข้อผิดพลาด กำลังลองอีกครั้ง…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"นำอุปกรณ์ออกแล้ว"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"ไม่พบ"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"ใช้การควบคุมไม่ได้"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"เข้าถึง <xliff:g id="DEVICE">%1$s</xliff:g> ไม่ได้ ตรวจสอบแอป <xliff:g id="APPLICATION">%2$s</xliff:g> ให้แน่ใจว่ายังใช้การควบคุมได้และการตั้งค่าของแอปไม่เปลี่ยนแปลง"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"เปิดแอป"</string>
<string name="controls_error_generic" msgid="352500456918362905">"โหลดสถานะไม่ได้"</string>
<string name="controls_error_failed" msgid="960228639198558525">"พบข้อผิดพลาด โปรดลองอีกครั้ง"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"กำลังดำเนินการ"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index b9b379c..041214f 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Ilipat sa kanan sa itaas"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Ilipat sa kaliwa sa ibaba"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Ilipat sa kanan sa ibaba"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"I-dismiss"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Huwag ipakita sa bubble ang mga pag-uusap"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Makipag-chat gamit ang mga bubble"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Lumalabas bilang mga nakalutang na icon o bubble ang mga bagong pag-uusap. I-tap para buksan ang bubble. I-drag para ilipat ito."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Mag-swipe para tumingin ng higit pa"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Nilo-load ang rekomendasyon"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Isara ang session ng media na ito"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Ituloy"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Hindi aktibo, tingnan ang app"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Nagka-error, sinusubukan ulit…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Inalis ang device"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Hindi nahanap"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Hindi available ang kontrol"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Hindi ma-access ang <xliff:g id="DEVICE">%1$s</xliff:g>. Tingnan ang <xliff:g id="APPLICATION">%2$s</xliff:g> app para matiyak na available pa rin ang kontrol at hindi nabago ang mga setting ng app."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Buksan ang app"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Hindi ma-load ang status"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Nagka-error, subukan ulit"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Isinasagawa"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 48268e7..e4892cf 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Sağ üste taşı"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Sol alta taşı"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Sağ alta taşı"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Kapat"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Görüşmeyi baloncuk olarak görüntüleme"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Baloncukları kullanarak sohbet edin"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Yeni görüşmeler kayan simgeler veya baloncuk olarak görünür. Açmak için baloncuğa dokunun. Baloncuğu taşımak için sürükleyin."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Diğer öğeleri görmek için hızlıca kaydırın"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Öneriler yükleniyor"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Bu medya oturumunu kapat"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Devam ettir"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Devre dışı, uygulamaya bakın"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Hata, yeniden deneniyor…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Cihaz kaldırıldı"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Bulunamadı"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Kontrol kullanılamıyor"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> cihazına erişilemedi Kontrolün hâlâ kullanılabilir olduğundan ve uygulama ayarlarının değişmediğinden emin olmak için <xliff:g id="APPLICATION">%2$s</xliff:g> uygulamasını kontrol edin."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Uygulama aç"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Durum yüklenemiyor"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Hata, yeniden deneyin"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Devam ediyor"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 38a478c..4c39f43 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -1012,9 +1012,10 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Перемістити праворуч угору"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Перемістити ліворуч униз"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Перемістити праворуч униз"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Закрити"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Не показувати спливаючі чати для розмов"</string>
- <string name="bubbles_user_education_title" msgid="5547017089271445797">"Чат зі спливаючими сповіщеннями"</string>
+ <string name="bubbles_user_education_title" msgid="5547017089271445797">"Спливаючий чат"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Нові повідомлення чату з\'являються у вигляді спливаючих значків. Щоб відкрити чат, натисніть його, а щоб перемістити – перетягніть."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Налаштовуйте спливаючі чати будь-коли"</string>
<string name="bubbles_user_education_manage" msgid="1391639189507036423">"Натисніть \"Налаштувати\", щоб вимкнути спливаючі чати від цього додатка"</string>
@@ -1074,9 +1075,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Гортайте, щоб переглянути інші"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Завантаження рекомендацій"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Закрити цей сеанс медіа"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Відновити"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Неактивно, перейдіть у додаток"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Помилка. Повторна спроба…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Пристрій вилучено"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Не знайдено"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Елемент керування недоступний"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g>: немає доступу. Перевірте в додатку <xliff:g id="APPLICATION">%2$s</xliff:g>, чи його налаштування не змінились і чи елемент керування доступний."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Відкрити додаток"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Не вдалося завантажити статус"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Помилка. Спробуйте знову"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Виконується"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index ac99a7b..feb894a 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"اوپر دائیں جانب لے جائيں"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"نیچے بائیں جانب لے جائیں"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"نیچے دائیں جانب لے جائیں"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"برخاست کریں"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"بلبلہ گفتگو نہ کریں"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"بلبلے کے ذریعے چیٹ کریں"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"نئی گفتگوئیں فلوٹنگ آئیکن یا بلبلے کے طور پر ظاہر ہوں گی۔ بلبلہ کھولنے کے لیے تھپتھپائیں۔ اسے منتقل کرنے کے لیے گھسیٹیں۔"</string>
@@ -1013,17 +1014,14 @@
<string name="notification_content_system_nav_changed" msgid="5077913144844684544">"سسٹم نیویگیشن اپ ڈیٹ کیا گیا۔ تبدیلیاں کرنے کے لیے، ترتیبات پر جائیں۔"</string>
<string name="notification_content_gesture_nav_available" msgid="4431460803004659888">"سسٹم نیویگیشن اپ ڈیٹ کرنے کے لیے ترتیبات پر جائیں"</string>
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"اسٹینڈ بائی"</string>
- <!-- no translation found for priority_onboarding_title (2893070698479227616) -->
- <skip />
- <!-- no translation found for priority_onboarding_behavior (5342816047020432929) -->
- <skip />
+ <string name="priority_onboarding_title" msgid="2893070698479227616">"گفتگو کو ترجیح پر سیٹ کیا گیا"</string>
+ <string name="priority_onboarding_behavior" msgid="5342816047020432929">"ترجیحی گفتگوئیں یہ ہوگی:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"گفتگو کے سیکشن میں سب سے اوپر دکھائیں"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"مقفل سکرین پر پروفائل کی تصویر دکھائیں"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"ایپس کے سب سے اوپر فلوٹنگ بلبلہ کے طور پر ظاہر ہوں"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"ڈسٹرب نہ کریں میں مداخلت کریں"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"سمجھ آ گئی"</string>
- <!-- no translation found for priority_onboarding_settings_button_title (6663601574303585927) -->
- <skip />
+ <string name="priority_onboarding_settings_button_title" msgid="6663601574303585927">"ترتیبات"</string>
<string name="magnification_overlay_title" msgid="6584179429612427958">"میگنیفیکیشن اوورلے ونڈو"</string>
<string name="magnification_window_title" msgid="4863914360847258333">"میگنیفکیشن ونڈو"</string>
<string name="magnification_controls_title" msgid="8421106606708891519">"میگنیفکیشن ونڈو کنٹرولز"</string>
@@ -1065,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"مزید دیکھنے کیلئے سوائپ کریں"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"تجاویز لوڈ ہو رہی ہیں"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"اس میڈیا سیشن کو بند کریں"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"دوبارہ شروع کریں"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"غیر فعال، ایپ چیک کریں"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"خرابی، دوبارہ کوشش کی جا رہی ہے…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"آلہ ہٹا دیا گیا"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"نہیں ملا"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"کنٹرول دستیاب نہیں ہے"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> تک رسائی حاصل نہیں ہو سکی۔ اس بات کو یقینی بنانے کے لیے کہ کنٹرول ابھی بھی دستیاب ہے اور ایپ کی ترتیبات تبدیل نہیں ہوئی، تو <xliff:g id="APPLICATION">%2$s</xliff:g> ایپ چیک کریں۔"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"ایپ کھولیں"</string>
<string name="controls_error_generic" msgid="352500456918362905">"صورتحال لوڈ نہیں ہو سکتی"</string>
<string name="controls_error_failed" msgid="960228639198558525">"خرابی، دوبارہ کوشش کریں"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"پیشرفت میں"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 518f60c..1145fa7 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -725,7 +725,7 @@
<string name="notification_unblockable_desc" msgid="2073030886006190804">"Bu bildirishnomalarni tahrirlash imkonsiz."</string>
<string name="notification_multichannel_desc" msgid="7414593090056236179">"Ushbu bildirishnomalar guruhi bu yerda sozlanmaydi"</string>
<string name="notification_delegate_header" msgid="1264510071031479920">"Ishonchli bildirishnoma"</string>
- <string name="notification_channel_dialog_title" msgid="6856514143093200019">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasining barcha bildirishnomalari"</string>
+ <string name="notification_channel_dialog_title" msgid="6856514143093200019">"Barcha <xliff:g id="APP_NAME">%1$s</xliff:g> bildirishnomalari"</string>
<string name="see_more_title" msgid="7409317011708185729">"Yana"</string>
<string name="appops_camera" msgid="5215967620896725715">"Bu ilova kameradan foydalanmoqda."</string>
<string name="appops_microphone" msgid="8805468338613070149">"Bu ilova mikrofondan foydalanmoqda."</string>
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Yuqori oʻngga surish"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Quyi chapga surish"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Quyi oʻngga surish"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Yopish"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Suhbatlar bulutchalar shaklida chiqmasin"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Bulutchalar yordamida subhatlashish"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Yangi xabarlar qalqib chiquvchi belgilar yoki bulutchalar kabi chiqadi. Xabarni ochish uchun bildirishnoma ustiga bosing. Xabarni qayta joylash uchun bildirishnomani suring."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Batafsil axborot olish uchun suring"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Tavsiyalar yuklanmoqda"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Bu media seansni yopish"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Davom etish"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Nofaol. Ilovani tekshiring"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Xato, qayta urinilmoqda…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Qurilma olib tashlandi"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Topilmadi"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Boshqarish imkonsiz"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g> ochilmadi. <xliff:g id="APPLICATION">%2$s</xliff:g> ilovasining sozlamalari oʻzgarmaganini va hali ham boshqarishga ruxsat borligini tekshiring."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Ilovani ochish"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Holat axboroti yuklanmadi"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Xato, qayta urining"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Bajarilmoqda"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 00e0cf7..8cd238c 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Chuyển lên trên cùng bên phải"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Chuyển tới dưới cùng bên trái"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Chuyển tới dưới cùng bên phải"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Loại bỏ"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Dừng trò chuyện bằng bong bóng"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Trò chuyện bằng bong bóng trò chuyện"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Các cuộc trò chuyện mới hiển thị dưới dạng biểu tượng nổi hoặc bong bóng trò chuyện. Nhấn để mở bong bóng trò chuyện. Kéo để di chuyển bong bóng trò chuyện."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Vuốt để xem thêm"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Đang tải các đề xuất"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Đóng phiên đa phương tiện này"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Tiếp tục"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Không hoạt động, hãy kiểm tra ứng dụng"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Lỗi, đang thử lại…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Đã xóa thiết bị"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Không tìm thấy"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Không có chức năng điều khiển"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Không thể sử dụng <xliff:g id="DEVICE">%1$s</xliff:g>. Hãy kiểm tra ứng dụng <xliff:g id="APPLICATION">%2$s</xliff:g> để đảm bảo rằng vẫn chức năng điều khiển vẫn dùng được và thông tin cài đặt của ứng dụng chưa thay đổi."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Mở ứng dụng"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Không tải được trạng thái"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Lỗi, hãy thử lại"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Đang thực hiện"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 2664830..86f43c9 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"移至右上角"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"移至左下角"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"移至右下角"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"关闭"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"不以对话泡形式显示对话"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"使用对话泡聊天"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"新对话会以浮动图标或对话泡形式显示。点按即可打开对话泡。拖动即可移动对话泡。"</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"滑动可查看更多结构"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在加载推荐内容"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"关闭此媒体会话"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"继续播放"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"无效,请检查应用"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"出现错误,正在重试…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"设备已移除"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"未找到"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"控件不可用"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"无法访问<xliff:g id="DEVICE">%1$s</xliff:g>。请查看<xliff:g id="APPLICATION">%2$s</xliff:g>应用,确保其中仍有该控件,并且应用设置没有更改。"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"打开应用"</string>
<string name="controls_error_generic" msgid="352500456918362905">"无法加载状态"</string>
<string name="controls_error_failed" msgid="960228639198558525">"出现错误,请重试"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"正在进行"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 34b7690..6d9ee99 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"移去右上角"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"移去左下角"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"移去右下角"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"關閉"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"不要透過小視窗顯示對話"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"使用小視窗進行即時通訊"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"新對話會以浮動圖示 (小視窗) 顯示。輕按即可開啟小視窗。拖曳即可移動小視窗。"</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"滑動以查看更多"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在載入建議"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"關閉此媒體版面"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"已停用,請檢查應用程式"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"發生錯誤,正在重試…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"已移除裝置"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"找不到"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"無法使用控制功能"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"無法存取 <xliff:g id="DEVICE">%1$s</xliff:g>。請檢查 <xliff:g id="APPLICATION">%2$s</xliff:g> 應用程式,確定控制功能仍可使用,同時應用程式設定並無變更。"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"開啟應用程式"</string>
<string name="controls_error_generic" msgid="352500456918362905">"無法載入狀態"</string>
<string name="controls_error_failed" msgid="960228639198558525">"發生錯誤,請再試一次"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"進行中"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 5f3911a..11e2be0 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"移至右上方"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"移至左下方"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"移至右下方"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"關閉"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"不要以對話框形式顯示對話"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"使用對話框進行即時通訊"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"新的對話會以浮動圖示或對話框形式顯示。輕觸即可開啟對話框,拖曳則可移動對話框。"</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"滑動即可查看其他結構"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"正在載入建議控制項"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"關閉這個媒體工作階段"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"繼續播放"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"無效,請查看應用程式"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"發生錯誤,正在重試…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"裝置已遭到移除"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"找不到控制項"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"無法使用控制項"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"無法存取「<xliff:g id="DEVICE">%1$s</xliff:g>」。請查看 <xliff:g id="APPLICATION">%2$s</xliff:g> 應用程式,確認當中是否仍有相關控制項,且應用程式設定沒有任何異動。"</string>
+ <string name="controls_open_app" msgid="483650971094300141">"開啟應用程式"</string>
<string name="controls_error_generic" msgid="352500456918362905">"無法載入狀態"</string>
<string name="controls_error_failed" msgid="960228639198558525">"發生錯誤,請再試一次"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"進行中"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 9b56c20..3587921 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -1002,7 +1002,8 @@
<string name="bubble_accessibility_action_move_top_right" msgid="6916868852433483569">"Hambisa phezulu ngakwesokudla"</string>
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Hambisa inkinobho ngakwesokunxele"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Hambisa inkinobho ngakwesokudla"</string>
- <string name="bubble_dismiss_text" msgid="7071770411580452911">"Cashisa"</string>
+ <!-- no translation found for bubble_dismiss_text (1314082410868930066) -->
+ <skip />
<string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Ungayibhamuzi ingxoxo"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Xoxa usebenzisa amabhamuza"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Izingxoxo ezintsha zivela njengezithonjana ezintantayo, noma amabhamuza. Thepha ukuze uvule ibhamuza. Hudula ukuze ulihambise."</string>
@@ -1062,9 +1063,13 @@
<string name="controls_structure_tooltip" msgid="4355922222944447867">"Swayipha ukuze ubone okuningi"</string>
<string name="controls_seeding_in_progress" msgid="3033855341410264148">"Ilayisha izincomo"</string>
<string name="controls_media_close_session" msgid="9023534788828414585">"Vala leseshini yemidiya"</string>
+ <string name="controls_media_resume" msgid="1933520684481586053">"Qalisa kabusha"</string>
<string name="controls_error_timeout" msgid="794197289772728958">"Akusebenzi, hlola uhlelo lokusebenza"</string>
<string name="controls_error_retryable" msgid="864025882878378470">"Iphutha, iyazama futhi…"</string>
- <string name="controls_error_removed" msgid="6299213591234723805">"Idivayisi isusiwe"</string>
+ <string name="controls_error_removed" msgid="6675638069846014366">"Ayitholakali"</string>
+ <string name="controls_error_removed_title" msgid="1207794911208047818">"Ukulawula akutholakali"</string>
+ <string name="controls_error_removed_message" msgid="2885911717034750542">"Ayikwazanga ukufinyelela ku-<xliff:g id="DEVICE">%1$s</xliff:g>. Hlola uhlelo lokusebenza le-<xliff:g id="APPLICATION">%2$s</xliff:g> ukuqinisekisa ukuthi ukulawula kusatholakala nokuthi amasethingi wohlelo lokusebenza awakashintshi."</string>
+ <string name="controls_open_app" msgid="483650971094300141">"Vula uhlelo"</string>
<string name="controls_error_generic" msgid="352500456918362905">"Ayikwazi ukulayisha isimo"</string>
<string name="controls_error_failed" msgid="960228639198558525">"Iphutha, zama futhi"</string>
<string name="controls_in_progress" msgid="4421080500238215939">"Iyaqhubeka"</string>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 0314fc8..48ff5c6 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1256,7 +1256,7 @@
<string name="manage_notifications_history_text">History</string>
<!-- Section title for notifications that have recently appeared. [CHAR LIMIT=40] -->
- <string name="notification_section_header_incoming">Incoming</string>
+ <string name="notification_section_header_incoming">New</string>
<!-- Section title for notifications that do not vibrate or make noise. [CHAR LIMIT=40] -->
<string name="notification_section_header_gentle">Silent</string>
@@ -2641,7 +2641,7 @@
<!-- Action in accessibility menu to move the stack of bubbles to the bottom right of the screen. [CHAR LIMIT=30]-->
<string name="bubble_accessibility_action_move_bottom_right">Move bottom right</string>
<!-- Text used for the bubble dismiss area. Bubbles dragged to, or flung towards, this area will go away. [CHAR LIMIT=20] -->
- <string name="bubble_dismiss_text">Dismiss</string>
+ <string name="bubble_dismiss_text">Dismiss bubble</string>
<!-- Button text to stop a conversation from bubbling [CHAR LIMIT=60]-->
<string name="bubbles_dont_bubble_conversation">Don\u2019t bubble conversation</string>
<!-- Title text for the bubbles feature education cling shown when a bubble is on screen for the first time. [CHAR LIMIT=60]-->
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 9d8c545..f639c88 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -141,14 +141,6 @@
mLayoutTransition.setAnimateParentHierarchy(false);
}
- // Temporary workaround to allow KeyguardStatusView to inflate a copy for Universal Smartspace.
- // Eventually the existing copy will be reparented instead, and we won't need this.
- public KeyguardSliceView(Context context, AttributeSet attributeSet) {
- this(context, attributeSet, Dependency.get(ActivityStarter.class),
- Dependency.get(ConfigurationController.class), Dependency.get(TunerService.class),
- context.getResources());
- }
-
@Override
protected void onFinishInflate() {
super.onFinishInflate();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index a181ce4..5a1c997 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -18,10 +18,7 @@
import android.app.ActivityManager;
import android.app.IActivityManager;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Handler;
@@ -43,8 +40,6 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.shared.system.SurfaceViewRequestReceiver;
-import com.android.systemui.shared.system.UniversalSmartspaceUtils;
import com.android.systemui.statusbar.policy.ConfigurationController;
import java.io.FileDescriptor;
@@ -127,21 +122,6 @@
}
};
- private final BroadcastReceiver mUniversalSmartspaceBroadcastReceiver =
- new BroadcastReceiver() {
- private final SurfaceViewRequestReceiver mReceiver = new SurfaceViewRequestReceiver();
-
- @Override
- public void onReceive(Context context, Intent i) {
- // TODO(b/148159743): Restrict to Pixel Launcher.
- if (UniversalSmartspaceUtils.ACTION_REQUEST_SMARTSPACE_VIEW.equals(i.getAction())) {
- mReceiver.onReceive(context,
- i.getBundleExtra(UniversalSmartspaceUtils.INTENT_BUNDLE_KEY),
- inflate(mContext, R.layout.keyguard_status_area, null));
- }
- }
- };
-
public KeyguardStatusView(Context context) {
this(context, null, 0);
}
@@ -336,8 +316,6 @@
super.onAttachedToWindow();
Dependency.get(KeyguardUpdateMonitor.class).registerCallback(mInfoCallback);
Dependency.get(ConfigurationController.class).addCallback(this);
- getContext().registerReceiver(mUniversalSmartspaceBroadcastReceiver,
- new IntentFilter(UniversalSmartspaceUtils.ACTION_REQUEST_SMARTSPACE_VIEW));
}
@Override
@@ -345,7 +323,6 @@
super.onDetachedFromWindow();
Dependency.get(KeyguardUpdateMonitor.class).removeCallback(mInfoCallback);
Dependency.get(ConfigurationController.class).removeCallback(this);
- getContext().unregisterReceiver(mUniversalSmartspaceBroadcastReceiver);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 1dd6409..dbe5a77 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -34,6 +34,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
@@ -632,6 +633,7 @@
windowFlags,
PixelFormat.TRANSLUCENT);
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
+ lp.setFitInsetsTypes(lp.getFitInsetsTypes() & ~WindowInsets.Type.ime());
lp.setTitle("BiometricPrompt");
lp.token = windowToken;
return lp;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 97a7304..7f78ddf 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -303,10 +303,10 @@
mDotPath = info.dotPath;
if (mExpandedView != null) {
- mExpandedView.update(/* bubble */ this);
+ mExpandedView.update(this /* bubble */);
}
if (mIconView != null) {
- mIconView.setRenderedBubble(/* bubble */ this);
+ mIconView.setRenderedBubble(this /* bubble */);
}
}
@@ -548,13 +548,13 @@
}
private boolean shouldSuppressNotification() {
- if (mEntry == null) return false;
+ if (mEntry == null) return true;
return mEntry.getBubbleMetadata() != null
&& mEntry.getBubbleMetadata().isNotificationSuppressed();
}
boolean shouldAutoExpand() {
- if (mEntry == null) return false;
+ if (mEntry == null) return mShouldAutoExpand;
Notification.BubbleMetadata metadata = mEntry.getBubbleMetadata();
return (metadata != null && metadata.getAutoExpandBubble()) || mShouldAutoExpand;
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index cf793f0..35cac4d 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -156,6 +156,7 @@
private final ShadeController mShadeController;
private final FloatingContentCoordinator mFloatingContentCoordinator;
private final BubbleDataRepository mDataRepository;
+ private BubbleLogger mLogger = new BubbleLoggerImpl();
private BubbleData mBubbleData;
private ScrimView mBubbleScrim;
@@ -317,6 +318,7 @@
BubbleDataRepository dataRepository,
SysUiState sysUiState,
INotificationManager notificationManager,
+ @Nullable IStatusBarService statusBarService,
WindowManager windowManager) {
dumpManager.registerDumpable(TAG, this);
mContext = context;
@@ -387,8 +389,10 @@
mSurfaceSynchronizer = synchronizer;
mWindowManager = windowManager;
- mBarService = IStatusBarService.Stub.asInterface(
- ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+ mBarService = statusBarService == null
+ ? IStatusBarService.Stub.asInterface(
+ ServiceManager.getService(Context.STATUS_BAR_SERVICE))
+ : statusBarService;
mBubbleScrim = new ScrimView(mContext);
@@ -617,7 +621,7 @@
if (mStackView == null) {
mStackView = new BubbleStackView(
mContext, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator,
- mSysUiState, mNotificationShadeWindowController, this::onAllBubblesAnimatedOut,
+ mSysUiState, this::onAllBubblesAnimatedOut,
this::onImeVisibilityChanged);
mStackView.addView(mBubbleScrim);
if (mExpandListener != null) {
@@ -894,9 +898,11 @@
}
void promoteBubbleFromOverflow(Bubble bubble) {
+ mLogger.log(bubble, BubbleLogger.Event.BUBBLE_OVERFLOW_REMOVE_BACK_TO_STACK);
bubble.setInflateSynchronously(mInflateSynchronously);
- setIsBubble(bubble, /* isBubble */ true);
- mBubbleData.promoteBubbleFromOverflow(bubble, mStackView, mBubbleIconFactory);
+ bubble.setShouldAutoExpand(true);
+ bubble.markUpdatedAt(System.currentTimeMillis());
+ setIsBubble(bubble, true /* isBubble */);
}
/**
@@ -910,20 +916,17 @@
Bubble bubble = mBubbleData.getBubbleInStackWithKey(key);
if (bubble != null) {
mBubbleData.setSelectedBubble(bubble);
+ mBubbleData.setExpanded(true);
} else {
bubble = mBubbleData.getOverflowBubbleWithKey(key);
if (bubble != null) {
- bubble.setShouldAutoExpand(true);
promoteBubbleFromOverflow(bubble);
} else if (entry.canBubble()) {
// It can bubble but it's not -- it got aged out of the overflow before it
// was dismissed or opened, make it a bubble again.
- setIsBubble(entry, true);
- updateBubble(entry, true /* suppressFlyout */, false /* showInShade */);
+ setIsBubble(entry, true /* isBubble */, true /* autoExpand */);
}
}
-
- mBubbleData.setExpanded(true);
}
/**
@@ -967,13 +970,17 @@
}
void updateBubble(NotificationEntry notif, boolean suppressFlyout, boolean showInShade) {
- // Lazy init stack view when a bubble is created
- ensureStackViewCreated();
// If this is an interruptive notif, mark that it's interrupted
if (notif.getImportance() >= NotificationManager.IMPORTANCE_HIGH) {
notif.setInterruption();
}
- Bubble bubble = mBubbleData.getOrCreateBubble(notif);
+ Bubble bubble = mBubbleData.getOrCreateBubble(notif, null /* persistedBubble */);
+ inflateAndAdd(bubble, suppressFlyout, showInShade);
+ }
+
+ void inflateAndAdd(Bubble bubble, boolean suppressFlyout, boolean showInShade) {
+ // Lazy init stack view when a bubble is created
+ ensureStackViewCreated();
bubble.setInflateSynchronously(mInflateSynchronously);
bubble.inflate(
b -> {
@@ -1119,7 +1126,8 @@
}
}
- private void setIsBubble(@NonNull final NotificationEntry entry, final boolean isBubble) {
+ private void setIsBubble(@NonNull final NotificationEntry entry, final boolean isBubble,
+ final boolean autoExpand) {
Objects.requireNonNull(entry);
if (isBubble) {
entry.getSbn().getNotification().flags |= FLAG_BUBBLE;
@@ -1127,7 +1135,12 @@
entry.getSbn().getNotification().flags &= ~FLAG_BUBBLE;
}
try {
- mBarService.onNotificationBubbleChanged(entry.getKey(), isBubble, 0);
+ int flags = 0;
+ if (autoExpand) {
+ flags = Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
+ flags |= Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE;
+ }
+ mBarService.onNotificationBubbleChanged(entry.getKey(), isBubble, flags);
} catch (RemoteException e) {
// Bad things have happened
}
@@ -1141,13 +1154,15 @@
b.disable(FLAG_BUBBLE);
}
if (b.getEntry() != null) {
- setIsBubble(b.getEntry(), isBubble);
+ // Updating the entry to be a bubble will trigger our normal update flow
+ setIsBubble(b.getEntry(), isBubble, b.shouldAutoExpand());
} else {
- try {
- mBarService.onNotificationBubbleChanged(b.getKey(), isBubble, 0);
- } catch (RemoteException e) {
- // Bad things have happened
- }
+ // If we have no entry to update, it's a persisted bubble so
+ // we need to add it to the stack ourselves
+ Bubble bubble = mBubbleData.getOrCreateBubble(null, b /* persistedBubble */);
+ inflateAndAdd(bubble, bubble.shouldAutoExpand() /* suppressFlyout */,
+ !bubble.shouldAutoExpand() /* showInShade */);
+
}
}
@@ -1199,7 +1214,7 @@
}
}
} else {
- if (bubble.isBubble() && bubble.showInShade()) {
+ if (bubble.isBubble()) {
setIsBubble(bubble, false /* isBubble */);
}
if (bubble.getEntry() != null && bubble.getEntry().getRow() != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index 996a555..24d44d5 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -115,7 +115,7 @@
/** Bubbles that aged out to overflow. */
private final List<Bubble> mOverflowBubbles;
/** Bubbles that are being loaded but haven't been added to the stack just yet. */
- private final List<Bubble> mPendingBubbles;
+ private final HashMap<String, Bubble> mPendingBubbles;
private Bubble mSelectedBubble;
private boolean mShowingOverflow;
private boolean mExpanded;
@@ -151,7 +151,7 @@
mContext = context;
mBubbles = new ArrayList<>();
mOverflowBubbles = new ArrayList<>();
- mPendingBubbles = new ArrayList<>();
+ mPendingBubbles = new HashMap<>();
mStateChange = new Update(mBubbles, mOverflowBubbles);
mMaxBubbles = mContext.getResources().getInteger(R.integer.bubbles_max_rendered);
mMaxOverflowBubbles = mContext.getResources().getInteger(R.integer.bubbles_max_overflow);
@@ -203,62 +203,46 @@
dispatchPendingChanges();
}
- public void promoteBubbleFromOverflow(Bubble bubble, BubbleStackView stack,
- BubbleIconFactory factory) {
- if (DEBUG_BUBBLE_DATA) {
- Log.d(TAG, "promoteBubbleFromOverflow: " + bubble);
- }
- mLogger.log(bubble, BubbleLogger.Event.BUBBLE_OVERFLOW_REMOVE_BACK_TO_STACK);
- moveOverflowBubbleToPending(bubble);
- // Preserve new order for next repack, which sorts by last updated time.
- bubble.inflate(
- b -> {
- b.setShouldAutoExpand(true);
- b.markUpdatedAt(mTimeSource.currentTimeMillis());
- notificationEntryUpdated(bubble, false /* suppressFlyout */,
- true /* showInShade */);
- },
- mContext, stack, factory, false /* skipInflation */);
- }
-
void setShowingOverflow(boolean showingOverflow) {
mShowingOverflow = showingOverflow;
}
- private void moveOverflowBubbleToPending(Bubble b) {
- mOverflowBubbles.remove(b);
- mPendingBubbles.add(b);
- }
-
/**
* Constructs a new bubble or returns an existing one. Does not add new bubbles to
* bubble data, must go through {@link #notificationEntryUpdated(Bubble, boolean, boolean)}
* for that.
+ *
+ * @param entry The notification entry to use, only null if it's a bubble being promoted from
+ * the overflow that was persisted over reboot.
+ * @param persistedBubble The bubble to use, only non-null if it's a bubble being promoted from
+ * the overflow that was persisted over reboot.
*/
- Bubble getOrCreateBubble(NotificationEntry entry) {
- String key = entry.getKey();
- Bubble bubble = getBubbleInStackWithKey(entry.getKey());
- if (bubble != null) {
- bubble.setEntry(entry);
- } else {
- bubble = getOverflowBubbleWithKey(key);
- if (bubble != null) {
- moveOverflowBubbleToPending(bubble);
- bubble.setEntry(entry);
- return bubble;
+ Bubble getOrCreateBubble(NotificationEntry entry, Bubble persistedBubble) {
+ String key = entry != null ? entry.getKey() : persistedBubble.getKey();
+ Bubble bubbleToReturn = getBubbleInStackWithKey(key);
+
+ if (bubbleToReturn == null) {
+ bubbleToReturn = getOverflowBubbleWithKey(key);
+ if (bubbleToReturn != null) {
+ // Promoting from overflow
+ mOverflowBubbles.remove(bubbleToReturn);
+ } else if (mPendingBubbles.containsKey(key)) {
+ // Update while it was pending
+ bubbleToReturn = mPendingBubbles.get(key);
+ } else if (entry != null) {
+ // New bubble
+ bubbleToReturn = new Bubble(entry, mSuppressionListener);
+ } else {
+ // Persisted bubble being promoted
+ bubbleToReturn = persistedBubble;
}
- // Check for it in pending
- for (int i = 0; i < mPendingBubbles.size(); i++) {
- Bubble b = mPendingBubbles.get(i);
- if (b.getKey().equals(entry.getKey())) {
- b.setEntry(entry);
- return b;
- }
- }
- bubble = new Bubble(entry, mSuppressionListener);
- mPendingBubbles.add(bubble);
}
- return bubble;
+
+ if (entry != null) {
+ bubbleToReturn.setEntry(entry);
+ }
+ mPendingBubbles.put(key, bubbleToReturn);
+ return bubbleToReturn;
}
/**
@@ -270,7 +254,7 @@
if (DEBUG_BUBBLE_DATA) {
Log.d(TAG, "notificationEntryUpdated: " + bubble);
}
- mPendingBubbles.remove(bubble); // No longer pending once we're here
+ mPendingBubbles.remove(bubble.getKey()); // No longer pending once we're here
Bubble prevBubble = getBubbleInStackWithKey(bubble.getKey());
suppressFlyout |= bubble.getEntry() == null
|| !bubble.getEntry().getRanking().visuallyInterruptive();
@@ -408,10 +392,8 @@
Log.d(TAG, "doRemove: " + key);
}
// If it was pending remove it
- for (int i = 0; i < mPendingBubbles.size(); i++) {
- if (mPendingBubbles.get(i).getKey().equals(key)) {
- mPendingBubbles.remove(mPendingBubbles.get(i));
- }
+ if (mPendingBubbles.containsKey(key)) {
+ mPendingBubbles.remove(key);
}
int indexToRemove = indexForKey(key);
if (indexToRemove == -1) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index c3dcc0b..db79802 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -490,7 +490,7 @@
if (DEBUG_BUBBLE_EXPANDED_VIEW) {
Log.d(TAG, "update: bubble=" + (bubble != null ? bubble.getKey() : "null"));
}
- boolean isNew = mBubble == null;
+ boolean isNew = mBubble == null || didBackingContentChange(bubble);
if (isNew || bubble != null && bubble.getKey().equals(mBubble.getKey())) {
mBubble = bubble;
mSettingsIcon.setContentDescription(getResources().getString(
@@ -523,6 +523,12 @@
}
}
+ private boolean didBackingContentChange(Bubble newBubble) {
+ boolean prevWasIntentBased = mBubble != null && mPendingIntent != null;
+ boolean newIsIntentBased = newBubble.getBubbleIntent() != null;
+ return prevWasIntentBased != newIsIntentBased;
+ }
+
/**
* Lets activity view know it should be shown / populated with activity content.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
index 3e694b9..b4672c1 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
@@ -75,6 +75,20 @@
}
return false;
}
+
+ @Override
+ public int getColumnCountForAccessibility(RecyclerView.Recycler recycler,
+ RecyclerView.State state) {
+ int bubbleCount = state.getItemCount();
+ int columnCount = super.getColumnCountForAccessibility(recycler, state);
+ if (bubbleCount < columnCount) {
+ // If there are 4 columns and bubbles <= 3,
+ // TalkBack says "AppName 1 of 4 in list 4 items"
+ // This is a workaround until TalkBack bug is fixed for GridLayoutManager
+ return bubbleCount;
+ }
+ return columnCount;
+ }
}
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 95c8d08..ba56346 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -79,7 +79,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ContrastColorUtil;
-import com.android.internal.widget.ViewClippingUtil;
import com.android.systemui.Interpolators;
import com.android.systemui.Prefs;
import com.android.systemui.R;
@@ -292,20 +291,6 @@
private ViewTreeObserver.OnDrawListener mSystemGestureExcludeUpdater =
this::updateSystemGestureExcludeRects;
- private ViewClippingUtil.ClippingParameters mClippingParameters =
- new ViewClippingUtil.ClippingParameters() {
-
- @Override
- public boolean shouldFinish(View view) {
- return false;
- }
-
- @Override
- public boolean isClippingEnablingAllowed(View view) {
- return !mIsExpanded;
- }
- };
-
/** Float property that 'drags' the flyout. */
private final FloatPropertyCompat mFlyoutCollapseProperty =
new FloatPropertyCompat("FlyoutCollapseSpring") {
@@ -348,8 +333,6 @@
@NonNull
private final SurfaceSynchronizer mSurfaceSynchronizer;
- private final NotificationShadeWindowController mNotificationShadeWindowController;
-
/**
* Callback to run when the IME visibility changes - BubbleController uses this to update the
* Bubbles window focusability flags with the WindowManager.
@@ -682,7 +665,6 @@
@Nullable SurfaceSynchronizer synchronizer,
FloatingContentCoordinator floatingContentCoordinator,
SysUiState sysUiState,
- NotificationShadeWindowController notificationShadeWindowController,
Runnable allBubblesAnimatedOutAction,
Consumer<Boolean> onImeVisibilityChanged) {
super(context);
@@ -691,7 +673,6 @@
mInflater = LayoutInflater.from(context);
mSysUiState = sysUiState;
- mNotificationShadeWindowController = notificationShadeWindowController;
Resources res = getResources();
mMaxBubbles = res.getInteger(R.integer.bubbles_max_rendered);
@@ -1399,7 +1380,6 @@
mBubbleContainer.addView(bubble.getIconView(), 0,
new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
- ViewClippingUtil.setClippingDeactivated(bubble.getIconView(), true, mClippingParameters);
animateInFlyoutForBubble(bubble);
requestUpdate();
logBubbleEvent(bubble, SysUiStatsLog.BUBBLE_UICHANGED__ACTION__POSTED);
@@ -1802,7 +1782,7 @@
public void subtractObscuredTouchableRegion(Region touchableRegion, View view) {
// If the notification shade is expanded, or the manage menu is open, we shouldn't let the
// ActivityView steal any touch events from any location.
- if (mNotificationShadeWindowController.getPanelExpanded() || mShowingManage) {
+ if (!mIsExpanded || mShowingManage) {
touchableRegion.setEmpty();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index fd1f879..3ef2044 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -1034,13 +1034,13 @@
mMagnetizedStack.getFlingToTargetMinVelocity() /* default */);
final float maxVelocity = Settings.Secure.getFloat(contentResolver,
"bubble_dismiss_stick_max_velocity",
- mMagnetizedStack.getStickToTargetMaxVelocity() /* default */);
+ mMagnetizedStack.getStickToTargetMaxXVelocity() /* default */);
final float targetWidth = Settings.Secure.getFloat(contentResolver,
"bubble_dismiss_target_width_percent",
mMagnetizedStack.getFlingToTargetWidthPercent() /* default */);
mMagnetizedStack.setFlingToTargetMinVelocity(minVelocity);
- mMagnetizedStack.setStickToTargetMaxVelocity(maxVelocity);
+ mMagnetizedStack.setStickToTargetMaxXVelocity(maxVelocity);
mMagnetizedStack.setFlingToTargetWidthPercent(targetWidth);
return mMagnetizedStack;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java
index d1d07f6..097932e 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.view.WindowManager;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.bubbles.BubbleData;
import com.android.systemui.bubbles.BubbleDataRepository;
@@ -70,6 +71,7 @@
BubbleDataRepository bubbleDataRepository,
SysUiState sysUiState,
INotificationManager notifManager,
+ IStatusBarService statusBarService,
WindowManager windowManager) {
return new BubbleController(
context,
@@ -91,6 +93,7 @@
bubbleDataRepository,
sysUiState,
notifManager,
+ statusBarService,
windowManager);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
index 0731920..45ba1e6 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
@@ -190,11 +190,6 @@
fun countFavoritesForComponent(componentName: ComponentName): Int
/**
- * TEMPORARY for testing
- */
- fun resetFavorites()
-
- /**
* Interface for structure to pass data to [ControlsFavoritingActivity].
*/
interface LoadData {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
index 93f0c7f..ebdcdcc 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
@@ -524,13 +524,6 @@
}
}
- override fun resetFavorites() {
- executor.execute {
- Favorites.clear()
- persistenceWrapper.storeFavorites(Favorites.getAllStructures())
- }
- }
-
override fun refreshStatus(componentName: ComponentName, control: Control) {
if (!confirmAvailability()) {
Log.d(TAG, "Controls not available")
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
index 9e7cf1a..353367e 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
@@ -87,9 +87,7 @@
deviceType: Int
): KClass<out Behavior> {
return when {
- status == Control.STATUS_UNKNOWN -> StatusBehavior::class
- status == Control.STATUS_ERROR -> StatusBehavior::class
- status == Control.STATUS_NOT_FOUND -> StatusBehavior::class
+ status != Control.STATUS_OK -> StatusBehavior::class
deviceType == DeviceTypes.TYPE_CAMERA -> TouchBehavior::class
template is ToggleTemplate -> ToggleBehavior::class
template is StatelessTemplate -> TouchBehavior::class
@@ -123,7 +121,11 @@
private val onDialogCancel: () -> Unit = { lastChallengeDialog = null }
val deviceType: Int
- get() = cws.control?.let { it.getDeviceType() } ?: cws.ci.deviceType
+ get() = cws.control?.let { it.deviceType } ?: cws.ci.deviceType
+ val controlStatus: Int
+ get() = cws.control?.let { it.status } ?: Control.STATUS_UNKNOWN
+ val controlTemplate: ControlTemplate
+ get() = cws.control?.let { it.controlTemplate } ?: ControlTemplate.NO_TEMPLATE
init {
val ld = layout.getBackground() as LayerDrawable
@@ -140,14 +142,16 @@
cancelUpdate?.run()
- val (controlStatus, template) = cws.control?.let {
- title.setText(it.getTitle())
- subtitle.setText(it.getSubtitle())
- Pair(it.status, it.controlTemplate)
- } ?: run {
+ // For the following statuses only, assume the title/subtitle could not be set properly
+ // by the app and instead use the last known information from favorites
+ if (controlStatus == Control.STATUS_UNKNOWN || controlStatus == Control.STATUS_NOT_FOUND) {
title.setText(cws.ci.controlTitle)
subtitle.setText(cws.ci.controlSubtitle)
- Pair(Control.STATUS_UNKNOWN, ControlTemplate.NO_TEMPLATE)
+ } else {
+ cws.control?.let {
+ title.setText(it.title)
+ subtitle.setText(it.subtitle)
+ }
}
cws.control?.let {
@@ -161,7 +165,8 @@
}
isLoading = false
- behavior = bindBehavior(behavior, findBehaviorClass(controlStatus, template, deviceType))
+ behavior = bindBehavior(behavior,
+ findBehaviorClass(controlStatus, controlTemplate, deviceType))
updateContentDescription()
}
@@ -256,7 +261,13 @@
}
internal fun applyRenderInfo(enabled: Boolean, offset: Int, animated: Boolean = true) {
- val ri = RenderInfo.lookup(context, cws.componentName, deviceType, offset)
+ val deviceTypeOrError = if (controlStatus == Control.STATUS_OK ||
+ controlStatus == Control.STATUS_UNKNOWN) {
+ deviceType
+ } else {
+ RenderInfo.ERROR_ICON
+ }
+ val ri = RenderInfo.lookup(context, cws.componentName, deviceTypeOrError, offset)
val fg = context.resources.getColorStateList(ri.foreground, context.theme)
val newText = nextStatusText
nextStatusText = ""
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index d31b6eb..0f5aef7 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -19,16 +19,13 @@
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ObjectAnimator
-import android.app.AlertDialog
import android.content.ComponentName
import android.content.Context
-import android.content.DialogInterface
import android.content.Intent
import android.content.SharedPreferences
import android.content.res.Configuration
import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable
-import android.os.Process
import android.service.controls.Control
import android.util.Log
import android.util.TypedValue
@@ -36,7 +33,6 @@
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.view.WindowManager
import android.view.animation.AccelerateInterpolator
import android.view.animation.DecelerateInterpolator
import android.widget.AdapterView
@@ -272,8 +268,7 @@
private fun createMenu() {
val items = arrayOf(
context.resources.getString(R.string.controls_menu_add),
- context.resources.getString(R.string.controls_menu_edit),
- "Reset"
+ context.resources.getString(R.string.controls_menu_edit)
)
var adapter = ArrayAdapter<String>(context, R.layout.controls_more_item, items)
@@ -298,10 +293,6 @@
0 -> startFavoritingActivity(view.context, selectedStructure)
// 1: Edit controls
1 -> startEditingActivity(view.context, selectedStructure)
- // 2: TEMPORARY for reset controls
- 2 -> showResetConfirmation()
- else -> Log.w(ControlsUiController.TAG,
- "Unsupported index ($pos) on 'more' menu selection")
}
dismiss()
}
@@ -312,39 +303,6 @@
})
}
- private fun showResetConfirmation() {
- val builder = AlertDialog.Builder(
- context,
- android.R.style.Theme_DeviceDefault_Dialog_Alert
- ).apply {
- setMessage("For testing purposes: Would you like to " +
- "reset your favorited device controls?")
- setPositiveButton(
- android.R.string.ok,
- DialogInterface.OnClickListener { dialog, _ ->
- val userHandle = Process.myUserHandle()
- val userContext = context.createContextAsUser(userHandle, 0)
- val prefs = userContext.getSharedPreferences(
- "controls_prefs", Context.MODE_PRIVATE)
- prefs.edit().remove("SeedingCompleted").apply()
- controlsController.get().resetFavorites()
- dialog.dismiss()
- context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
- })
- setNegativeButton(
- android.R.string.cancel,
- DialogInterface.OnClickListener {
- dialog, _ -> dialog.cancel()
- }
- )
- }
- builder.create().apply {
- getWindow().apply {
- setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY)
- }
- }.show()
- }
-
private fun createDropDown(items: List<SelectionItem>) {
items.forEach {
RenderInfo.registerComponentIcon(it.componentName, it.icon)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
index 09d41bd..3f17a4f 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
@@ -35,6 +35,7 @@
) {
companion object {
const val APP_ICON_ID = -1
+ const val ERROR_ICON = -1000
private val iconMap = SparseArray<Drawable>()
private val appIconMap = ArrayMap<ComponentName, Drawable>()
@@ -156,7 +157,8 @@
DeviceTypes.TYPE_CURTAIN to R.drawable.ic_device_blinds,
DeviceTypes.TYPE_DOOR to R.drawable.ic_device_door,
DeviceTypes.TYPE_SHUTTER to R.drawable.ic_device_window,
- DeviceTypes.TYPE_HEATER to R.drawable.ic_device_thermostat
+ DeviceTypes.TYPE_HEATER to R.drawable.ic_device_thermostat,
+ RenderInfo.ERROR_ICON to R.drawable.ic_error_outline
).withDefault {
R.drawable.ic_device_unknown
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt
index 6bf1897..dac5537 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt
@@ -19,6 +19,7 @@
import android.app.AlertDialog
import android.app.PendingIntent
import android.content.DialogInterface
+import android.content.Intent
import android.content.pm.PackageManager
import android.service.controls.Control
import android.view.View
@@ -74,6 +75,7 @@
DialogInterface.OnClickListener { dialog, _ ->
try {
cws.control?.getAppIntent()?.send()
+ context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
} catch (e: PendingIntent.CanceledException) {
cvh.setTransientStatus(
cvh.context.resources.getString(R.string.controls_error_failed))
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 5e5ebe9..bc95a25 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -779,7 +779,8 @@
@VisibleForTesting
protected final class PowerOptionsAction extends SinglePressAction {
private PowerOptionsAction() {
- super(R.drawable.ic_lock_power_off, R.string.global_action_power_options);
+ super(com.android.systemui.R.drawable.ic_settings_power,
+ R.string.global_action_power_options);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPopupMenu.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPopupMenu.java
index 6b71f1e..1dbbb4d 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPopupMenu.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPopupMenu.java
@@ -19,6 +19,7 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
+import android.util.LayoutDirection;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.WindowManager;
@@ -106,7 +107,11 @@
listView.setPadding(0, mMenuVerticalPadding, 0, mMenuVerticalPadding);
setWidth(width);
- setHorizontalOffset(getAnchorView().getWidth() - mGlobalActionsSidePadding - width);
+ if (getAnchorView().getLayoutDirection() == LayoutDirection.LTR) {
+ setHorizontalOffset(getAnchorView().getWidth() - mGlobalActionsSidePadding - width);
+ } else {
+ setHorizontalOffset(mGlobalActionsSidePadding);
+ }
}
super.show();
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
index 03b1ddc..7f7e108 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipAnimationController.java
@@ -17,7 +17,6 @@
package com.android.systemui.pip;
import android.animation.Animator;
-import android.animation.RectEvaluator;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.content.Context;
@@ -27,7 +26,6 @@
import android.view.animation.Interpolator;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Interpolators;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -76,12 +74,15 @@
|| direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN;
}
+ private final Interpolator mFastOutSlowInInterpolator;
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
private PipTransitionAnimator mCurrentAnimator;
@Inject
PipAnimationController(Context context, PipSurfaceTransactionHelper helper) {
+ mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
+ com.android.internal.R.interpolator.fast_out_slow_in);
mSurfaceTransactionHelper = helper;
}
@@ -103,11 +104,10 @@
}
@SuppressWarnings("unchecked")
- PipTransitionAnimator getAnimator(SurfaceControl leash, Rect startBounds, Rect endBounds,
- Rect sourceHintRect) {
+ PipTransitionAnimator getAnimator(SurfaceControl leash, Rect startBounds, Rect endBounds) {
if (mCurrentAnimator == null) {
mCurrentAnimator = setupPipTransitionAnimator(
- PipTransitionAnimator.ofBounds(leash, startBounds, endBounds, sourceHintRect));
+ PipTransitionAnimator.ofBounds(leash, startBounds, endBounds));
} else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
&& mCurrentAnimator.isRunning()) {
// If we are still animating the fade into pip, then just move the surface and ensure
@@ -122,7 +122,7 @@
} else {
mCurrentAnimator.cancel();
mCurrentAnimator = setupPipTransitionAnimator(
- PipTransitionAnimator.ofBounds(leash, startBounds, endBounds, sourceHintRect));
+ PipTransitionAnimator.ofBounds(leash, startBounds, endBounds));
}
return mCurrentAnimator;
}
@@ -133,7 +133,7 @@
private PipTransitionAnimator setupPipTransitionAnimator(PipTransitionAnimator animator) {
animator.setSurfaceTransactionHelper(mSurfaceTransactionHelper);
- animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ animator.setInterpolator(mFastOutSlowInInterpolator);
animator.setFloatValues(FRACTION_START, FRACTION_END);
return animator;
}
@@ -331,7 +331,6 @@
@Override
void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
getSurfaceTransactionHelper()
- .resetScale(tx, leash, getDestinationBounds())
.crop(tx, leash, getDestinationBounds())
.round(tx, leash, shouldApplyCornerRadius());
tx.show(leash);
@@ -347,46 +346,35 @@
}
static PipTransitionAnimator<Rect> ofBounds(SurfaceControl leash,
- Rect startValue, Rect endValue, Rect sourceHintRect) {
- // Just for simplicity we'll interpolate between the source rect hint insets and empty
- // insets to calculate the window crop
- final Rect initialStartValue = new Rect(startValue);
- final Rect sourceHintRectInsets = sourceHintRect != null
- ? new Rect(sourceHintRect.left - startValue.left,
- sourceHintRect.top - startValue.top,
- startValue.right - sourceHintRect.right,
- startValue.bottom - sourceHintRect.bottom)
- : null;
- final Rect sourceInsets = new Rect(0, 0, 0, 0);
-
+ Rect startValue, Rect endValue) {
// construct new Rect instances in case they are recycled
return new PipTransitionAnimator<Rect>(leash, ANIM_TYPE_BOUNDS,
endValue, new Rect(startValue), new Rect(endValue)) {
- private final RectEvaluator mRectEvaluator = new RectEvaluator(new Rect());
- private final RectEvaluator mInsetsEvaluator = new RectEvaluator(new Rect());
+ private final Rect mTmpRect = new Rect();
+
+ private int getCastedFractionValue(float start, float end, float fraction) {
+ return (int) (start * (1 - fraction) + end * fraction + .5f);
+ }
@Override
void applySurfaceControlTransaction(SurfaceControl leash,
SurfaceControl.Transaction tx, float fraction) {
final Rect start = getStartValue();
final Rect end = getEndValue();
- Rect bounds = mRectEvaluator.evaluate(fraction, start, end);
- setCurrentValue(bounds);
+ mTmpRect.set(
+ getCastedFractionValue(start.left, end.left, fraction),
+ getCastedFractionValue(start.top, end.top, fraction),
+ getCastedFractionValue(start.right, end.right, fraction),
+ getCastedFractionValue(start.bottom, end.bottom, fraction));
+ setCurrentValue(mTmpRect);
if (inScaleTransition()) {
if (isOutPipDirection(getTransitionDirection())) {
- getSurfaceTransactionHelper().scale(tx, leash, end, bounds);
+ getSurfaceTransactionHelper().scale(tx, leash, end, mTmpRect);
} else {
- getSurfaceTransactionHelper().scale(tx, leash, start, bounds);
+ getSurfaceTransactionHelper().scale(tx, leash, start, mTmpRect);
}
} else {
- if (sourceHintRectInsets != null) {
- Rect insets = mInsetsEvaluator.evaluate(fraction, sourceInsets,
- sourceHintRectInsets);
- getSurfaceTransactionHelper().scaleAndCrop(tx, leash, initialStartValue,
- bounds, insets);
- } else {
- getSurfaceTransactionHelper().scale(tx, leash, start, bounds);
- }
+ getSurfaceTransactionHelper().crop(tx, leash, mTmpRect);
}
tx.apply();
}
@@ -402,11 +390,11 @@
@Override
void onEndTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
+ if (!inScaleTransition()) return;
// NOTE: intentionally does not apply the transaction here.
// this end transaction should get executed synchronously with the final
// WindowContainerTransaction in task organizer
- getSurfaceTransactionHelper()
- .resetScale(tx, leash, getDestinationBounds())
+ getSurfaceTransactionHelper().resetScale(tx, leash, getDestinationBounds())
.crop(tx, leash, getDestinationBounds());
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
index 2657694..0d3a16e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -296,14 +296,6 @@
*/
public boolean onDisplayRotationChanged(Rect outBounds, Rect oldBounds, Rect outInsetBounds,
int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) {
- // Calculate the snap fraction of the current stack along the old movement bounds
- final Rect postChangeStackBounds = new Rect(oldBounds);
- final float snapFraction = getSnapFraction(postChangeStackBounds);
-
- // Update the display layout, note that we have to do this on every rotation even if we
- // aren't in PIP since we need to update the display layout to get the right resources
- mDisplayLayout.rotateTo(mContext.getResources(), toRotation);
-
// Bail early if the event is not sent to current {@link #mDisplayInfo}
if ((displayId != mDisplayInfo.displayId) || (fromRotation == toRotation)) {
return false;
@@ -320,6 +312,13 @@
return false;
}
+ // Calculate the snap fraction of the current stack along the old movement bounds
+ final Rect postChangeStackBounds = new Rect(oldBounds);
+ final float snapFraction = getSnapFraction(postChangeStackBounds);
+
+ // Update the display layout
+ mDisplayLayout.rotateTo(mContext.getResources(), toRotation);
+
// Populate the new {@link #mDisplayInfo}.
// The {@link DisplayInfo} queried from DisplayManager would be the one before rotation,
// therefore, the width/height may require a swap first.
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipSurfaceTransactionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/PipSurfaceTransactionHelper.java
index 65ea887..fc41d2e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipSurfaceTransactionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipSurfaceTransactionHelper.java
@@ -44,7 +44,6 @@
private final float[] mTmpFloat9 = new float[9];
private final RectF mTmpSourceRectF = new RectF();
private final RectF mTmpDestinationRectF = new RectF();
- private final Rect mTmpDestinationRect = new Rect();
@Inject
public PipSurfaceTransactionHelper(Context context, ConfigurationController configController) {
@@ -91,30 +90,7 @@
mTmpDestinationRectF.set(destinationBounds);
mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
- .setPosition(leash, mTmpDestinationRectF.left, mTmpDestinationRectF.top);
- return this;
- }
-
- /**
- * Operates the scale (setMatrix) on a given transaction and leash
- * @return same {@link PipSurfaceTransactionHelper} instance for method chaining
- */
- PipSurfaceTransactionHelper scaleAndCrop(SurfaceControl.Transaction tx, SurfaceControl leash,
- Rect sourceBounds, Rect destinationBounds, Rect insets) {
- mTmpSourceRectF.set(sourceBounds);
- mTmpDestinationRect.set(sourceBounds);
- mTmpDestinationRect.inset(insets);
- // Scale by the shortest edge and offset such that the top/left of the scaled inset source
- // rect aligns with the top/left of the destination bounds
- final float scale = sourceBounds.width() <= sourceBounds.height()
- ? (float) destinationBounds.width() / sourceBounds.width()
- : (float) destinationBounds.height() / sourceBounds.height();
- final float left = destinationBounds.left - insets.left * scale;
- final float top = destinationBounds.top - insets.top * scale;
- mTmpTransform.setScale(scale, scale);
- tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
- .setWindowCrop(leash, mTmpDestinationRect)
- .setPosition(leash, left, top);
+ .setPosition(leash, destinationBounds.left, destinationBounds.top);
return this;
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index 42e0c56..c6f144a 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -143,10 +143,8 @@
case MSG_RESIZE_ANIMATE: {
Rect currentBounds = (Rect) args.arg2;
Rect toBounds = (Rect) args.arg3;
- Rect sourceHintRect = (Rect) args.arg4;
int duration = args.argi2;
- animateResizePip(currentBounds, toBounds, sourceHintRect,
- args.argi1 /* direction */, duration);
+ animateResizePip(currentBounds, toBounds, args.argi1 /* direction */, duration);
if (updateBoundsCallback != null) {
updateBoundsCallback.accept(toBounds);
}
@@ -296,8 +294,7 @@
public void onTransactionReady(int id, SurfaceControl.Transaction t) {
t.apply();
scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
- null /* sourceHintRect */, direction, animationDurationMs,
- null /* updateBoundsCallback */);
+ direction, animationDurationMs, null /* updateBoundsCallback */);
mInPip = false;
}
});
@@ -360,8 +357,7 @@
final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
- final Rect sourceHintRect = getValidSourceHintRect(info, currentBounds);
- scheduleAnimateResizePip(currentBounds, destinationBounds, sourceHintRect,
+ scheduleAnimateResizePip(currentBounds, destinationBounds,
TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
null /* updateBoundsCallback */);
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
@@ -372,21 +368,6 @@
}
}
- /**
- * Returns the source hint rect if it is valid (if provided and is contained by the current
- * task bounds).
- */
- private Rect getValidSourceHintRect(ActivityManager.RunningTaskInfo info, Rect sourceBounds) {
- final Rect sourceHintRect = info.pictureInPictureParams != null
- && info.pictureInPictureParams.hasSourceBoundsHint()
- ? info.pictureInPictureParams.getSourceRectHint()
- : null;
- if (sourceHintRect != null && sourceBounds.contains(sourceHintRect)) {
- return sourceHintRect;
- }
- return null;
- }
-
private void enterPipWithAlphaAnimation(Rect destinationBounds, long durationMs) {
// If we are fading the PIP in, then we should move the pip to the final location as
// soon as possible, but set the alpha immediately since the transaction can take a
@@ -571,13 +552,13 @@
Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
return;
}
- scheduleAnimateResizePip(mLastReportedBounds, toBounds, null /* sourceHintRect */,
+ scheduleAnimateResizePip(mLastReportedBounds, toBounds,
TRANSITION_DIRECTION_NONE, duration, updateBoundsCallback);
}
private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds,
- Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction,
- int durationMs, Consumer<Rect> updateBoundsCallback) {
+ @PipAnimationController.TransitionDirection int direction, int durationMs,
+ Consumer<Rect> updateBoundsCallback) {
if (!mInPip) {
// can be initiated in other component, ignore if we are no longer in PIP
return;
@@ -587,7 +568,6 @@
args.arg1 = updateBoundsCallback;
args.arg2 = currentBounds;
args.arg3 = destinationBounds;
- args.arg4 = sourceHintRect;
args.argi1 = direction;
args.argi2 = durationMs;
mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESIZE_ANIMATE, args));
@@ -687,8 +667,7 @@
}
final Rect destinationBounds = new Rect(originalBounds);
destinationBounds.offset(xOffset, yOffset);
- animateResizePip(originalBounds, destinationBounds, null /* sourceHintRect */,
- TRANSITION_DIRECTION_SAME, durationMs);
+ animateResizePip(originalBounds, destinationBounds, TRANSITION_DIRECTION_SAME, durationMs);
}
private void resizePip(Rect destinationBounds) {
@@ -766,7 +745,7 @@
WindowOrganizer.applyTransaction(wct);
}
- private void animateResizePip(Rect currentBounds, Rect destinationBounds, Rect sourceHintRect,
+ private void animateResizePip(Rect currentBounds, Rect destinationBounds,
@PipAnimationController.TransitionDirection int direction, int durationMs) {
if (Looper.myLooper() != mUpdateHandler.getLooper()) {
throw new RuntimeException("Callers should call scheduleAnimateResizePip() instead of "
@@ -778,7 +757,7 @@
return;
}
mPipAnimationController
- .getAnimator(mLeash, currentBounds, destinationBounds, sourceHintRect)
+ .getAnimator(mLeash, currentBounds, destinationBounds)
.setTransitionDirection(direction)
.setPipAnimationCallback(mPipAnimationCallback)
.setDuration(durationMs)
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 1ddb1f5..3cc9127 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -30,6 +30,7 @@
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
+import android.graphics.drawable.TransitionDrawable;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
@@ -76,6 +77,9 @@
public class PipTouchHandler {
private static final String TAG = "PipTouchHandler";
+ /** Duration of the dismiss scrim fading in/out. */
+ private static final int DISMISS_TRANSITION_DURATION_MS = 200;
+
// Allow dragging the PIP to a location to close it
private final boolean mEnableDismissDragToEdge;
// Allow PIP to resize to a slightly bigger state upon touch
@@ -249,6 +253,8 @@
mTargetView = new DismissCircleView(context);
mTargetViewContainer = new FrameLayout(context);
+ mTargetViewContainer.setBackgroundDrawable(
+ context.getDrawable(R.drawable.floating_dismiss_gradient_transition));
mTargetViewContainer.setClipChildren(false);
mTargetViewContainer.addView(mTargetView);
@@ -553,6 +559,9 @@
mMagneticTargetAnimator
.spring(DynamicAnimation.TRANSLATION_Y, 0f, mTargetSpringConfig)
.start();
+
+ ((TransitionDrawable) mTargetViewContainer.getBackground()).startTransition(
+ DISMISS_TRANSITION_DURATION_MS);
}
}
@@ -565,6 +574,9 @@
mTargetSpringConfig)
.withEndActions(() -> mTargetViewContainer.setVisibility(View.GONE))
.start();
+
+ ((TransitionDrawable) mTargetViewContainer.getBackground()).reverseTransition(
+ DISMISS_TRANSITION_DURATION_MS);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
index d7dd6f2..32ef063 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
@@ -22,6 +22,7 @@
import android.util.Log;
import android.widget.Switch;
+import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
@@ -41,14 +42,16 @@
private ActivityStarter mActivityStarter;
private long mMillisUntilFinished = 0;
private Callback mCallback = new Callback();
+ private UiEventLogger mUiEventLogger;
@Inject
public ScreenRecordTile(QSHost host, RecordingController controller,
- ActivityStarter activityStarter) {
+ ActivityStarter activityStarter, UiEventLogger uiEventLogger) {
super(host);
mController = controller;
mController.observe(this, mCallback);
mActivityStarter = activityStarter;
+ mUiEventLogger = uiEventLogger;
}
@Override
@@ -112,7 +115,6 @@
}
private void startCountdown() {
- Log.d(TAG, "Starting countdown");
// Close QS, otherwise the permission dialog appears beneath it
getHost().collapsePanels();
Intent intent = mController.getPromptIntent();
@@ -125,7 +127,6 @@
}
private void stopRecording() {
- Log.d(TAG, "Stopping recording from tile");
mController.stopRecording();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
index aa63b40..6a8c6149 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailItemView.java
@@ -95,14 +95,11 @@
mAvatar.setDrawableWithBadge(picture, userId);
}
- public void setAvatarEnabled(boolean enabled) {
- mAvatar.setEnabled(enabled);
- }
-
public void setDisabledByAdmin(boolean disabled) {
- mRestrictedPadlock.setVisibility(disabled ? View.VISIBLE : View.GONE);
- mName.setEnabled(!disabled);
- mAvatar.setEnabled(!disabled);
+ if (mRestrictedPadlock != null) {
+ mRestrictedPadlock.setVisibility(disabled ? View.VISIBLE : View.GONE);
+ }
+ setEnabled(!disabled);
}
public void setEnabled(boolean enabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index 89ce125..fba7a22 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -16,8 +16,12 @@
package com.android.systemui.qs.tiles;
+import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA;
+import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA;
+
import android.content.Context;
import android.content.Intent;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;
@@ -94,18 +98,21 @@
}
String name = getName(mContext, item);
if (item.picture == null) {
- v.bind(name, getDrawable(mContext, item), item.resolveId());
+ v.bind(name, getDrawable(mContext, item).mutate(), item.resolveId());
} else {
- v.bind(name, item.picture, item.info.id);
+ Drawable drawable = new BitmapDrawable(v.getResources(), item.picture);
+ drawable.setColorFilter(
+ item.isSwitchToEnabled ? null : getDisabledUserAvatarColorFilter());
+ v.bind(name, drawable, item.info.id);
}
v.setActivated(item.isCurrent);
+ v.setDisabledByAdmin(item.isDisabledByAdmin);
+ v.setEnabled(item.isSwitchToEnabled);
+ v.setAlpha(v.isEnabled() ? USER_SWITCH_ENABLED_ALPHA : USER_SWITCH_DISABLED_ALPHA);
+
if (item.isCurrent) {
mCurrentUserView = v;
}
- v.setDisabledByAdmin(item.isDisabledByAdmin);
- if (!item.isSwitchToEnabled) {
- v.setEnabled(false);
- }
v.setTag(item);
return v;
}
@@ -113,8 +120,14 @@
private static Drawable getDrawable(Context context,
UserSwitcherController.UserRecord item) {
Drawable icon = getIconDrawable(context, item);
- int iconColorRes = item.isCurrent ? R.color.qs_user_switcher_selected_avatar_icon_color
- : R.color.qs_user_switcher_avatar_icon_color;
+ int iconColorRes;
+ if (item.isCurrent) {
+ iconColorRes = R.color.qs_user_switcher_selected_avatar_icon_color;
+ } else if (!item.isSwitchToEnabled) {
+ iconColorRes = R.color.GM2_grey_600;
+ } else {
+ iconColorRes = R.color.qs_user_switcher_avatar_icon_color;
+ }
icon.setTint(context.getResources().getColor(iconColorRes, context.getTheme()));
int bgRes = item.isCurrent ? R.drawable.bg_avatar_selected : R.drawable.qs_bg_avatar;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index baa2dfd..8a012b8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -577,10 +577,6 @@
// Listen for nav bar mode changes
mNavBarMode = navModeController.addListener(this);
- // Listen for device provisioned/user setup
- updateEnabledState();
- startTracking();
-
// Listen for launcher package changes
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
filter.addDataScheme("package");
@@ -601,6 +597,13 @@
.commitUpdate(mContext.getDisplayId());
}
});
+
+ // Listen for user setup
+ startTracking();
+
+ // Connect to the service
+ updateEnabledState();
+ startConnectionToCurrentUser();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/Events.java b/packages/SystemUI/src/com/android/systemui/screenrecord/Events.java
new file mode 100644
index 0000000..9dede48
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/Events.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenrecord;
+
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
+
+/**
+ * Events related to the SystemUI screen recorder
+ */
+public class Events {
+
+ public enum ScreenRecordEvent implements UiEventLogger.UiEventEnum {
+ @UiEvent(doc = "Screen recording was started")
+ SCREEN_RECORD_START(299),
+ @UiEvent(doc = "Screen recording was stopped from the quick settings tile")
+ SCREEN_RECORD_END_QS_TILE(300),
+ @UiEvent(doc = "Screen recording was stopped from the notification")
+ SCREEN_RECORD_END_NOTIFICATION(301);
+
+ private final int mId;
+ ScreenRecordEvent(int id) {
+ mId = id;
+ }
+
+ @Override
+ public int getId() {
+ return mId;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index 2ddd6aa..f2e8599 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -36,6 +36,8 @@
import android.util.Log;
import android.widget.Toast;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.LongRunning;
@@ -63,22 +65,28 @@
private static final String ACTION_START = "com.android.systemui.screenrecord.START";
private static final String ACTION_STOP = "com.android.systemui.screenrecord.STOP";
+ private static final String ACTION_STOP_NOTIF =
+ "com.android.systemui.screenrecord.STOP_FROM_NOTIF";
private static final String ACTION_SHARE = "com.android.systemui.screenrecord.SHARE";
private static final String ACTION_DELETE = "com.android.systemui.screenrecord.DELETE";
private final RecordingController mController;
- private Notification.Builder mRecordingNotificationBuilder;
private ScreenRecordingAudioSource mAudioSource;
private boolean mShowTaps;
private boolean mOriginalShowTaps;
private ScreenMediaRecorder mRecorder;
private final Executor mLongExecutor;
+ private final UiEventLogger mUiEventLogger;
+ private final NotificationManager mNotificationManager;
@Inject
- public RecordingService(RecordingController controller, @LongRunning Executor executor) {
+ public RecordingService(RecordingController controller, @LongRunning Executor executor,
+ UiEventLogger uiEventLogger, NotificationManager notificationManager) {
mController = controller;
mLongExecutor = executor;
+ mUiEventLogger = uiEventLogger;
+ mNotificationManager = notificationManager;
}
/**
@@ -110,9 +118,6 @@
String action = intent.getAction();
Log.d(TAG, "onStartCommand " + action);
- NotificationManager notificationManager =
- (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
-
switch (action) {
case ACTION_START:
mAudioSource = ScreenRecordingAudioSource
@@ -135,10 +140,16 @@
startRecording();
break;
+ case ACTION_STOP_NOTIF:
case ACTION_STOP:
+ // only difference for actions is the log event
+ if (ACTION_STOP_NOTIF.equals(action)) {
+ mUiEventLogger.log(Events.ScreenRecordEvent.SCREEN_RECORD_END_NOTIFICATION);
+ } else {
+ mUiEventLogger.log(Events.ScreenRecordEvent.SCREEN_RECORD_END_QS_TILE);
+ }
stopRecording();
- notificationManager.cancel(NOTIFICATION_RECORDING_ID);
- saveRecording(notificationManager);
+ mNotificationManager.cancel(NOTIFICATION_RECORDING_ID);
stopSelf();
break;
@@ -154,7 +165,7 @@
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
// Remove notification
- notificationManager.cancel(NOTIFICATION_VIEW_ID);
+ mNotificationManager.cancel(NOTIFICATION_VIEW_ID);
startActivity(Intent.createChooser(shareIntent, shareLabel)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
@@ -173,7 +184,7 @@
Toast.LENGTH_LONG).show();
// Remove notification
- notificationManager.cancel(NOTIFICATION_VIEW_ID);
+ mNotificationManager.cancel(NOTIFICATION_VIEW_ID);
Log.d(TAG, "Deleted recording " + uri);
break;
}
@@ -190,14 +201,20 @@
super.onCreate();
}
+ @VisibleForTesting
+ protected ScreenMediaRecorder getRecorder() {
+ return mRecorder;
+ }
+
/**
* Begin the recording session
*/
private void startRecording() {
try {
- mRecorder.start();
+ getRecorder().start();
mController.updateState(true);
createRecordingNotification();
+ mUiEventLogger.log(Events.ScreenRecordEvent.SCREEN_RECORD_START);
} catch (IOException | RemoteException e) {
Toast.makeText(this,
R.string.screenrecord_start_error, Toast.LENGTH_LONG)
@@ -206,7 +223,8 @@
}
}
- private void createRecordingNotification() {
+ @VisibleForTesting
+ protected void createRecordingNotification() {
Resources res = getResources();
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
@@ -214,9 +232,7 @@
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(getString(R.string.screenrecord_channel_description));
channel.enableVibration(true);
- NotificationManager notificationManager =
- (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- notificationManager.createNotificationChannel(channel);
+ mNotificationManager.createNotificationChannel(channel);
Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
@@ -226,7 +242,9 @@
? res.getString(R.string.screenrecord_ongoing_screen_only)
: res.getString(R.string.screenrecord_ongoing_screen_and_audio);
- mRecordingNotificationBuilder = new Notification.Builder(this, CHANNEL_ID)
+
+ Intent stopIntent = getNotificationIntent(this);
+ Notification.Builder builder = new Notification.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_screenrecord)
.setContentTitle(notificationTitle)
.setContentText(getResources().getString(R.string.screenrecord_stop_text))
@@ -235,17 +253,28 @@
.setColor(getResources().getColor(R.color.GM2_red_700))
.setOngoing(true)
.setContentIntent(
- PendingIntent.getService(
- this, REQUEST_CODE, getStopIntent(this),
+ PendingIntent.getService(this, REQUEST_CODE, stopIntent,
PendingIntent.FLAG_UPDATE_CURRENT))
.addExtras(extras);
- notificationManager.notify(NOTIFICATION_RECORDING_ID,
- mRecordingNotificationBuilder.build());
- Notification notification = mRecordingNotificationBuilder.build();
- startForeground(NOTIFICATION_RECORDING_ID, notification);
+ startForeground(NOTIFICATION_RECORDING_ID, builder.build());
}
- private Notification createSaveNotification(ScreenMediaRecorder.SavedRecording recording) {
+ @VisibleForTesting
+ protected Notification createProcessingNotification() {
+ Resources res = getApplicationContext().getResources();
+ String notificationTitle = mAudioSource == ScreenRecordingAudioSource.NONE
+ ? res.getString(R.string.screenrecord_ongoing_screen_only)
+ : res.getString(R.string.screenrecord_ongoing_screen_and_audio);
+ Notification.Builder builder = new Notification.Builder(getApplicationContext(), CHANNEL_ID)
+ .setContentTitle(notificationTitle)
+ .setContentText(
+ getResources().getString(R.string.screenrecord_background_processing_label))
+ .setSmallIcon(R.drawable.ic_screenrecord);
+ return builder.build();
+ }
+
+ @VisibleForTesting
+ protected Notification createSaveNotification(ScreenMediaRecorder.SavedRecording recording) {
Uri uri = recording.getUri();
Intent viewIntent = new Intent(Intent.ACTION_VIEW)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION)
@@ -301,44 +330,39 @@
private void stopRecording() {
setTapsVisible(mOriginalShowTaps);
- mRecorder.end();
+ if (getRecorder() != null) {
+ getRecorder().end();
+ saveRecording();
+ } else {
+ Log.e(TAG, "stopRecording called, but recorder was null");
+ }
mController.updateState(false);
}
- private void saveRecording(NotificationManager notificationManager) {
- Resources res = getApplicationContext().getResources();
- String notificationTitle = mAudioSource == ScreenRecordingAudioSource.NONE
- ? res.getString(R.string.screenrecord_ongoing_screen_only)
- : res.getString(R.string.screenrecord_ongoing_screen_and_audio);
- Notification.Builder builder = new Notification.Builder(getApplicationContext(), CHANNEL_ID)
- .setContentTitle(notificationTitle)
- .setContentText(
- getResources().getString(R.string.screenrecord_background_processing_label))
- .setSmallIcon(R.drawable.ic_screenrecord);
- notificationManager.notify(NOTIFICATION_PROCESSING_ID, builder.build());
+ private void saveRecording() {
+ mNotificationManager.notify(NOTIFICATION_PROCESSING_ID, createProcessingNotification());
mLongExecutor.execute(() -> {
try {
Log.d(TAG, "saving recording");
- Notification notification = createSaveNotification(mRecorder.save());
+ Notification notification = createSaveNotification(getRecorder().save());
if (!mController.isRecording()) {
Log.d(TAG, "showing saved notification");
- notificationManager.notify(NOTIFICATION_VIEW_ID, notification);
+ mNotificationManager.notify(NOTIFICATION_VIEW_ID, notification);
}
} catch (IOException e) {
Log.e(TAG, "Error saving screen recording: " + e.getMessage());
Toast.makeText(this, R.string.screenrecord_delete_error, Toast.LENGTH_LONG)
.show();
} finally {
- notificationManager.cancel(NOTIFICATION_PROCESSING_ID);
+ mNotificationManager.cancel(NOTIFICATION_PROCESSING_ID);
}
});
}
private void setTapsVisible(boolean turnOn) {
int value = turnOn ? 1 : 0;
- Settings.System.putInt(getApplicationContext().getContentResolver(),
- Settings.System.SHOW_TOUCHES, value);
+ Settings.System.putInt(getContentResolver(), Settings.System.SHOW_TOUCHES, value);
}
/**
@@ -350,6 +374,15 @@
return new Intent(context, RecordingService.class).setAction(ACTION_STOP);
}
+ /**
+ * Get the recording notification content intent
+ * @param context
+ * @return
+ */
+ protected static Intent getNotificationIntent(Context context) {
+ return new Intent(context, RecordingService.class).setAction(ACTION_STOP_NOTIF);
+ }
+
private static Intent getShareIntent(Context context, String path) {
return new Intent(context, RecordingService.class).setAction(ACTION_SHARE)
.putExtra(EXTRA_PATH, path);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index a8c0324..5bee9a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -60,7 +60,11 @@
private final Handler mHandler;
- /** Re-usable map of top-level notifications to their sorted children if any.*/
+ /**
+ * Re-usable map of top-level notifications to their sorted children if any.
+ * If the top-level notification doesn't have children, its key will still exist in this map
+ * with its value explicitly set to null.
+ */
private final HashMap<NotificationEntry, List<NotificationEntry>> mTmpChildOrderMap =
new HashMap<>();
@@ -212,10 +216,19 @@
}
orderedChildren.add(ent);
} else {
- // Top-level notif
- mTmpChildOrderMap.put(ent, null);
+ // Top-level notif (either a summary or single notification)
+
+ // A child may have already added its summary to mTmpChildOrderMap with a
+ // list of children. This can happen since there's no guarantee summaries are
+ // sorted before its children.
+ if (!mTmpChildOrderMap.containsKey(ent)) {
+ // mTmpChildOrderMap's keyset is used to iterate through all entries, so it's
+ // necessary to add each top-level notif as a key
+ mTmpChildOrderMap.put(ent, null);
+ }
toShow.add(ent.getRow());
}
+
}
ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
index fc6c2be..1972b86 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
@@ -19,13 +19,16 @@
import android.app.Notification
import android.content.Context
import android.content.pm.LauncherApps
+import android.os.Handler
import android.service.notification.NotificationListenerService.Ranking
import android.service.notification.NotificationListenerService.RankingMap
import com.android.internal.statusbar.NotificationVisibility
import com.android.internal.widget.ConversationLayout
+import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.NotificationContentView
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator
import com.android.systemui.statusbar.phone.NotificationGroupManager
import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject
@@ -62,7 +65,8 @@
class ConversationNotificationManager @Inject constructor(
private val notificationEntryManager: NotificationEntryManager,
private val notificationGroupManager: NotificationGroupManager,
- private val context: Context
+ private val context: Context,
+ @Main private val mainHandler: Handler
) {
// Need this state to be thread safe, since it's accessed from the ui thread
// (NotificationEntryListener) and a bg thread (NotificationContentInflater)
@@ -72,32 +76,41 @@
init {
notificationEntryManager.addNotificationEntryListener(object : NotificationEntryListener {
-
override fun onNotificationRankingUpdated(rankingMap: RankingMap) {
fun getLayouts(view: NotificationContentView) =
sequenceOf(view.contractedChild, view.expandedChild, view.headsUpChild)
val ranking = Ranking()
- states.keys.asSequence()
+ val activeConversationEntries = states.keys.asSequence()
.mapNotNull { notificationEntryManager.getActiveNotificationUnfiltered(it) }
- .forEach { entry ->
- if (rankingMap.getRanking(entry.sbn.key, ranking) &&
- ranking.isConversation) {
- val important = ranking.channel.isImportantConversation
- var changed = false
- entry.row?.layouts?.asSequence()
- ?.flatMap(::getLayouts)
- ?.mapNotNull { it as? ConversationLayout }
- ?.forEach {
- if (important != it.isImportantConversation) {
- it.setIsImportantConversation(important)
- changed = true
- }
- }
- if (changed) {
- notificationGroupManager.updateIsolation(entry)
- }
+ for (entry in activeConversationEntries) {
+ if (rankingMap.getRanking(entry.sbn.key, ranking) && ranking.isConversation) {
+ val important = ranking.channel.isImportantConversation
+ val layouts = entry.row?.layouts?.asSequence()
+ ?.flatMap(::getLayouts)
+ ?.mapNotNull { it as? ConversationLayout }
+ ?: emptySequence()
+ var changed = false
+ for (layout in layouts) {
+ if (important == layout.isImportantConversation) {
+ continue
+ }
+ changed = true
+ if (important && entry.isMarkedForUserTriggeredMovement) {
+ // delay this so that it doesn't animate in until after
+ // the notif has been moved in the shade
+ mainHandler.postDelayed({
+ layout.setIsImportantConversation(
+ important, true /* animate */)
+ }, IMPORTANCE_ANIMATION_DELAY.toLong())
+ } else {
+ layout.setIsImportantConversation(important)
}
}
+ if (changed) {
+ notificationGroupManager.updateIsolation(entry)
+ }
+ }
+ }
}
override fun onEntryInflated(entry: NotificationEntry) {
@@ -177,9 +190,16 @@
private fun resetBadgeUi(row: ExpandableNotificationRow): Unit =
(row.layouts?.asSequence() ?: emptySequence())
- .flatMap { layout -> layout.allViews.asSequence()}
+ .flatMap { layout -> layout.allViews.asSequence() }
.mapNotNull { view -> view as? ConversationLayout }
.forEach { convoLayout -> convoLayout.setUnreadCount(0) }
private data class ConversationState(val unreadCount: Int, val notification: Notification)
+
+ companion object {
+ private const val IMPORTANCE_ANIMATION_DELAY =
+ StackStateAnimator.ANIMATION_DURATION_STANDARD +
+ StackStateAnimator.ANIMATION_DURATION_PRIORITY_CHANGE +
+ 100
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
index df3609b..1c076c4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/HighPriorityProvider.java
@@ -23,6 +23,9 @@
import com.android.systemui.statusbar.notification.collection.ListEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+
+import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -36,10 +39,14 @@
@Singleton
public class HighPriorityProvider {
private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
+ private final NotificationGroupManager mGroupManager;
@Inject
- public HighPriorityProvider(PeopleNotificationIdentifier peopleNotificationIdentifier) {
+ public HighPriorityProvider(
+ PeopleNotificationIdentifier peopleNotificationIdentifier,
+ NotificationGroupManager groupManager) {
mPeopleNotificationIdentifier = peopleNotificationIdentifier;
+ mGroupManager = groupManager;
}
/**
@@ -74,13 +81,25 @@
private boolean hasHighPriorityChild(ListEntry entry) {
+ List<NotificationEntry> children = null;
+
if (entry instanceof GroupEntry) {
- for (NotificationEntry child : ((GroupEntry) entry).getChildren()) {
+ // New notification pipeline
+ children = ((GroupEntry) entry).getChildren();
+ } else if (entry.getRepresentativeEntry() != null
+ && mGroupManager.isGroupSummary(entry.getRepresentativeEntry().getSbn())) {
+ // Old notification pipeline
+ children = mGroupManager.getChildren(entry.getRepresentativeEntry().getSbn());
+ }
+
+ if (children != null) {
+ for (NotificationEntry child : children) {
if (isHighPriority(child)) {
return true;
}
}
}
+
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java
index 87612f1..e445c9d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java
@@ -188,7 +188,9 @@
@Override
public boolean handleCloseControls(boolean save, boolean force) {
- mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, false);
+ if (mMetricsLogger != null) {
+ mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, false);
+ }
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
index e9d8958..f4afb91 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
@@ -53,7 +53,6 @@
import android.transition.TransitionSet;
import android.util.AttributeSet;
import android.util.Log;
-import android.util.Slog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
@@ -508,10 +507,10 @@
mBgHandler.post(
new UpdateChannelRunnable(mINotificationManager, mPackageName,
mAppUid, mSelectedAction, mNotificationChannel));
- mMainHandler.postDelayed(() -> {
- mEntry.markForUserTriggeredMovement(true);
- mVisualStabilityManager.temporarilyAllowReordering();
- }, StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ mEntry.markForUserTriggeredMovement(true);
+ mMainHandler.postDelayed(
+ mVisualStabilityManager::temporarilyAllowReordering,
+ StackStateAnimator.ANIMATION_DURATION_STANDARD);
}
private boolean shouldShowPriorityOnboarding() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java
index f1fe54a..186ffa6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PartialConversationInfo.java
@@ -148,8 +148,7 @@
}
private void bindHeader() {
- bindConversationDetails();
-
+ bindPackage();
// Delegate
bindDelegate();
}
@@ -180,51 +179,6 @@
});
}
- private void bindConversationDetails() {
- final TextView channelName = findViewById(R.id.parent_channel_name);
- channelName.setText(mNotificationChannel.getName());
-
- bindGroup();
- bindName();
- bindPackage();
- bindIcon();
- }
-
- private void bindName() {
- TextView name = findViewById(R.id.name);
- Bundle extras = mSbn.getNotification().extras;
- CharSequence nameString = extras.getCharSequence(Notification.EXTRA_CONVERSATION_TITLE, "");
- if (TextUtils.isEmpty(nameString)) {
- nameString = extras.getCharSequence(Notification.EXTRA_TITLE, "");
- }
- name.setText(nameString);
- }
-
- private void bindIcon() {
- ImageView image = findViewById(R.id.conversation_icon);
- if (mSbn.getNotification().extras.getBoolean(EXTRA_IS_GROUP_CONVERSATION, false)) {
- // TODO: maybe use a generic group icon, or a composite of recent senders
- image.setImageDrawable(mPkgIcon);
- } else {
- final List<Notification.MessagingStyle.Message> messages =
- Notification.MessagingStyle.Message.getMessagesFromBundleArray(
- (Parcelable[]) mSbn.getNotification().extras.get(
- Notification.EXTRA_MESSAGES));
-
- final Notification.MessagingStyle.Message latestMessage =
- Notification.MessagingStyle.findLatestIncomingMessage(messages);
- Icon personIcon = null;
- if (latestMessage != null && latestMessage.getSenderPerson() != null) {
- personIcon = latestMessage.getSenderPerson().getIcon();
- }
- if (personIcon != null) {
- image.setImageIcon(latestMessage.getSenderPerson().getIcon());
- } else {
- image.setImageDrawable(mPkgIcon);
- }
- }
- }
-
private void bindPackage() {
ApplicationInfo info;
try {
@@ -241,6 +195,10 @@
} catch (PackageManager.NameNotFoundException e) {
mPkgIcon = mPm.getDefaultActivityIcon();
}
+ TextView name = findViewById(R.id.name);
+ name.setText(mAppName);
+ ImageView image = findViewById(R.id.icon);
+ image.setImageDrawable(mPkgIcon);
}
private void bindDelegate() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 4c9cb20..c747a7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -262,7 +262,10 @@
stack.push(mView);
while (!stack.isEmpty()) {
View child = stack.pop();
- if (child instanceof ImageView) {
+ if (child instanceof ImageView
+ // Skip the importance ring for conversations, disabled cropping is needed for
+ // its animation
+ && child.getId() != com.android.internal.R.id.conversation_icon_badge_ring) {
((ImageView) child).setCropToPadding(true);
} else if (child instanceof ViewGroup){
ViewGroup group = (ViewGroup) child;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 325c8c0..b11ed23 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -146,6 +146,7 @@
import com.android.systemui.statusbar.phone.HeadsUpTouchHelper;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationGroupManager.OnGroupChangeListener;
import com.android.systemui.statusbar.phone.NotificationIconAreaController;
@@ -6633,6 +6634,7 @@
MetricsEvent.ACTION_LS_SHADE,
(int) (dragLengthY / mDisplayMetrics.density),
0 /* velocityDp - N/A */);
+ mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_PULL_SHADE_OPEN);
if (!mAmbientState.isDozing() || startingChild != null) {
// We have notifications, go to locked shade.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
index 8c3420a..83d398d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
@@ -20,6 +20,9 @@
import android.util.ArrayMap;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.EventLogConstants;
@@ -34,6 +37,56 @@
*/
@Singleton
public class LockscreenGestureLogger {
+
+ /**
+ * Contains Lockscreen related Westworld UiEvent enums.
+ */
+ public enum LockscreenUiEvent implements UiEventLogger.UiEventEnum {
+ @UiEvent(doc = "Lockscreen > Pull shade open")
+ LOCKSCREEN_PULL_SHADE_OPEN(539),
+
+ @UiEvent(doc = "Lockscreen > Tap on lock, locks phone")
+ LOCKSCREEN_LOCK_TAP(540),
+
+ @UiEvent(doc = "Lockscreen > Swipe down to open quick settings")
+ LOCKSCREEN_QUICK_SETTINGS_OPEN(541),
+
+ @UiEvent(doc = "Swipe down to open quick settings when unlocked")
+ LOCKSCREEN_UNLOCKED_QUICK_SETTINGS_OPEN(542),
+
+ @UiEvent(doc = "Lockscreen > Tap on lock, shows hint")
+ LOCKSCREEN_LOCK_SHOW_HINT(543),
+
+ @UiEvent(doc = "Notification shade > Tap to open quick settings")
+ LOCKSCREEN_NOTIFICATION_SHADE_QUICK_SETTINGS_OPEN(544),
+
+ @UiEvent(doc = "Lockscreen > Dialer")
+ LOCKSCREEN_DIALER(545),
+
+ @UiEvent(doc = "Lockscreen > Camera")
+ LOCKSCREEN_CAMERA(546),
+
+ @UiEvent(doc = "Lockscreen > Unlock gesture")
+ LOCKSCREEN_UNLOCK(547),
+
+ @UiEvent(doc = "Lockscreen > Tap on notification, false touch rejection")
+ LOCKSCREEN_NOTIFICATION_FALSE_TOUCH(548),
+
+ @UiEvent(doc = "Expand the notification panel while unlocked")
+ LOCKSCREEN_UNLOCKED_NOTIFICATION_PANEL_EXPAND(549);
+
+ private final int mId;
+
+ LockscreenUiEvent(int id) {
+ mId = id;
+ }
+
+ @Override
+ public int getId() {
+ return mId;
+ }
+ }
+
private ArrayMap<Integer, Integer> mLegacyMap;
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
@@ -55,6 +108,13 @@
}
/**
+ * Logs {@link LockscreenUiEvent}.
+ */
+ public void log(LockscreenUiEvent lockscreenUiEvent) {
+ new UiEventLoggerImpl().log(lockscreenUiEvent);
+ }
+
+ /**
* Record the location of a swipe gesture, expressed as percentages of the whole screen
* @param category the action
* @param xPercent x-location / width * 100
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
index 8a5c8b0..5d3910b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
@@ -45,6 +45,7 @@
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator.WakeUpListener;
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
import com.android.systemui.statusbar.policy.AccessibilityController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -436,6 +437,7 @@
private boolean handleLongClick(View view) {
mLockscreenGestureLogger.write(MetricsProto.MetricsEvent.ACTION_LS_LOCK,
0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
+ mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_LOCK_TAP);
mKeyguardIndicationController.showTransientIndication(
R.string.keyguard_indication_trust_disabled);
mKeyguardUpdateMonitor.onLockIconPressed();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 26e80ad..8954d98 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -59,6 +59,7 @@
import android.database.ContentObserver;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.hardware.display.DisplayManager;
import android.inputmethodservice.InputMethodService;
import android.net.Uri;
@@ -83,6 +84,7 @@
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.view.WindowInsetsController.Appearance;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
@@ -94,6 +96,8 @@
import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
import com.android.internal.view.AppearanceRegion;
@@ -217,11 +221,31 @@
* original handle hidden and we'll flip the visibilities once the
* {@link #mTasksFrozenListener} fires
*/
- private NavigationHandle mOrientationHandle;
+ private VerticalNavigationHandle mOrientationHandle;
private WindowManager.LayoutParams mOrientationParams;
private int mStartingQuickSwitchRotation;
private int mCurrentRotation;
private boolean mFixedRotationEnabled;
+ private ViewTreeObserver.OnGlobalLayoutListener mOrientationHandleGlobalLayoutListener;
+ private UiEventLogger mUiEventLogger;
+
+ @com.android.internal.annotations.VisibleForTesting
+ public enum NavBarActionEvent implements UiEventLogger.UiEventEnum {
+
+ @UiEvent(doc = "Assistant invoked via home button long press.")
+ NAVBAR_ASSIST_LONGPRESS(550);
+
+ private final int mId;
+
+ NavBarActionEvent(int id) {
+ mId = id;
+ }
+
+ @Override
+ public int getId() {
+ return mId;
+ }
+ }
/** Only for default display */
@Nullable
@@ -364,7 +388,8 @@
ShadeController shadeController,
NotificationRemoteInputManager notificationRemoteInputManager,
SystemActions systemActions,
- @Main Handler mainHandler) {
+ @Main Handler mainHandler,
+ UiEventLogger uiEventLogger) {
mAccessibilityManagerWrapper = accessibilityManagerWrapper;
mDeviceProvisionedController = deviceProvisionedController;
mStatusBarStateController = statusBarStateController;
@@ -384,6 +409,7 @@
mRecentsOptional = recentsOptional;
mSystemActions = systemActions;
mHandler = mainHandler;
+ mUiEventLogger = uiEventLogger;
}
// ----- Fragment Lifecycle Callbacks -----
@@ -519,6 +545,8 @@
getContext().getSystemService(DisplayManager.class).unregisterDisplayListener(this);
getBarTransitions().removeDarkIntensityListener(mOrientationHandleIntensityListener);
mWindowManager.removeView(mOrientationHandle);
+ mOrientationHandle.getViewTreeObserver().removeOnGlobalLayoutListener(
+ mOrientationHandleGlobalLayoutListener);
}
}
@@ -573,6 +601,20 @@
PixelFormat.TRANSLUCENT);
mWindowManager.addView(mOrientationHandle, mOrientationParams);
mOrientationHandle.setVisibility(View.GONE);
+ mOrientationHandleGlobalLayoutListener =
+ () -> {
+ if (mStartingQuickSwitchRotation == -1) {
+ return;
+ }
+
+ RectF boundsOnScreen = mOrientationHandle.computeHomeHandleBounds();
+ mOrientationHandle.mapRectFromViewToScreenCoords(boundsOnScreen, true);
+ Rect boundsRounded = new Rect();
+ boundsOnScreen.roundOut(boundsRounded);
+ mNavigationBarView.setOrientedHandleSamplingRegion(boundsRounded);
+ };
+ mOrientationHandle.getViewTreeObserver().addOnGlobalLayoutListener(
+ mOrientationHandleGlobalLayoutListener);
}
private void orientSecondaryHomeHandle() {
@@ -621,6 +663,7 @@
}
if (mNavigationBarView != null) {
mNavigationBarView.setVisibility(View.VISIBLE);
+ mNavigationBarView.setOrientedHandleSamplingRegion(null);
}
}
@@ -988,6 +1031,7 @@
return false;
}
mMetricsLogger.action(MetricsEvent.ACTION_ASSIST_LONG_PRESS);
+ mUiEventLogger.log(NavBarActionEvent.NAVBAR_ASSIST_LONGPRESS);
Bundle args = new Bundle();
args.putInt(
AssistManager.INVOCATION_TYPE_KEY, AssistManager.INVOCATION_HOME_BUTTON_LONG_PRESS);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 6b37ac3..4821d8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -35,6 +35,7 @@
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.annotation.DrawableRes;
+import android.annotation.Nullable;
import android.app.StatusBarManager;
import android.content.Context;
import android.content.res.Configuration;
@@ -158,6 +159,14 @@
*/
private ScreenPinningNotify mScreenPinningNotify;
private Rect mSamplingBounds = new Rect();
+ /**
+ * When quickswitching between apps of different orientations, we draw a secondary home handle
+ * in the position of the first app's orientation. This rect represents the region of that
+ * home handle so we can apply the correct light/dark luma on that.
+ * @see {@link NavigationBarFragment#mOrientationHandle}
+ */
+ @Nullable
+ private Rect mOrientedHandleSamplingRegion;
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
@@ -327,6 +336,10 @@
@Override
public Rect getSampledRegion(View sampledView) {
+ if (mOrientedHandleSamplingRegion != null) {
+ return mOrientedHandleSamplingRegion;
+ }
+
updateSamplingRect();
return mSamplingBounds;
}
@@ -897,6 +910,11 @@
}
}
+ void setOrientedHandleSamplingRegion(Rect orientedHandleSamplingRegion) {
+ mOrientedHandleSamplingRegion = orientedHandleSamplingRegion;
+ mRegionSamplingHelper.updateSamplingRect();
+ }
+
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
@@ -1190,6 +1208,8 @@
mIsVertical ? "true" : "false",
getLightTransitionsController().getCurrentDarkIntensity()));
+ pw.println(" mOrientedHandleSamplingRegion: " + mOrientedHandleSamplingRegion);
+
dumpButton(pw, "back", getBackButton());
dumpButton(pw, "home", getHomeButton());
dumpButton(pw, "rcnt", getRecentsButton());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 8889510..d884bdd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -104,9 +104,9 @@
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
-import com.android.systemui.statusbar.notification.stack.MediaHeaderView;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -2474,6 +2474,8 @@
} else {
mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_HINT,
0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
+ mLockscreenGestureLogger
+ .log(LockscreenUiEvent.LOCKSCREEN_LOCK_SHOW_HINT);
startUnlockHintAnimation();
}
}
@@ -3257,7 +3259,7 @@
int velocityDp = Math.abs((int) (vel / displayDensity));
if (start) {
mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_DIALER, lengthDp, velocityDp);
-
+ mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_DIALER);
mFalsingManager.onLeftAffordanceOn();
if (mFalsingManager.shouldEnforceBouncer()) {
mStatusBar.executeRunnableDismissingKeyguard(
@@ -3272,6 +3274,7 @@
mLastCameraLaunchSource)) {
mLockscreenGestureLogger.write(
MetricsEvent.ACTION_LS_CAMERA, lengthDp, velocityDp);
+ mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_CAMERA);
}
mFalsingManager.onCameraOn();
if (mFalsingManager.shouldEnforceBouncer()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index 57d36fc..a902e1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -47,6 +47,7 @@
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.io.FileDescriptor;
@@ -319,6 +320,8 @@
mLockscreenGestureLogger.writeAtFractionalPosition(MetricsEvent.ACTION_PANEL_VIEW_EXPAND,
(int) (event.getX() / width * 100), (int) (event.getY() / height * 100), rot);
+ mLockscreenGestureLogger
+ .log(LockscreenUiEvent.LOCKSCREEN_UNLOCKED_NOTIFICATION_PANEL_EXPAND);
}
protected void maybeVibrateOnOpening() {
@@ -378,6 +381,7 @@
int heightDp = (int) Math.abs((y - mInitialTouchY) / displayDensity);
int velocityDp = (int) Math.abs(vel / displayDensity);
mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_UNLOCK, heightDp, velocityDp);
+ mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_UNLOCK);
}
fling(vel, expand, isFalseTouch(x, y));
onTrackingStopped(expand);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 84da35b..45f0c49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -72,6 +72,7 @@
import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -374,6 +375,7 @@
mLockscreenGestureLogger.write(
MetricsEvent.ACTION_LS_NOTE,
0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
+ mLockscreenGestureLogger.log(LockscreenUiEvent.LOCKSCREEN_NOTIFICATION_FALSE_TOUCH);
mNotificationPanel.showTransientIndication(R.string.notification_tap_again);
ActivatableNotificationView previousView = mNotificationPanel.getActivatedChild();
if (previousView != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/VerticalNavigationHandle.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/VerticalNavigationHandle.java
index a15ca95..0cdf1d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/VerticalNavigationHandle.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/VerticalNavigationHandle.java
@@ -18,12 +18,14 @@
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.RectF;
import com.android.systemui.R;
/** Temporarily shown view when using QuickSwitch to switch between apps of different rotations */
public class VerticalNavigationHandle extends NavigationHandle {
private final int mWidth;
+ private final RectF mTmpBoundsRectF = new RectF();
public VerticalNavigationHandle(Context context) {
super(context);
@@ -32,16 +34,21 @@
@Override
protected void onDraw(Canvas canvas) {
+ canvas.drawRoundRect(computeHomeHandleBounds(), mRadius, mRadius, mPaint);
+ }
+
+ RectF computeHomeHandleBounds() {
int left;
int top;
int bottom;
int right;
-
+ int topStart = getLocationOnScreen()[1];
int radiusOffset = mRadius * 2;
right = getWidth() - mBottom;
- top = getHeight() / 2 - (mWidth / 2); /* (height of screen / 2) - (height of bar / 2) */
+ top = getHeight() / 2 - (mWidth / 2) - (topStart / 2);
left = getWidth() - mBottom - radiusOffset;
- bottom = getHeight() / 2 + (mWidth / 2);
- canvas.drawRoundRect(left, top, right, bottom, mRadius, mRadius, mPaint);
+ bottom = top + mWidth;
+ mTmpBoundsRectF.set(left, top, right, bottom);
+ return mTmpBoundsRectF;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 58f5d2a..0ca8ef0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -87,7 +87,7 @@
private boolean mHasOvalBg = false;
@VisibleForTesting
- public enum NavBarActionsEvent implements UiEventLogger.UiEventEnum {
+ public enum NavBarButtonEvent implements UiEventLogger.UiEventEnum {
@UiEvent(doc = "The home button was pressed in the navigation bar.")
NAVBAR_HOME_BUTTON_TAP(533),
@@ -111,7 +111,7 @@
private final int mId;
- NavBarActionsEvent(int id) {
+ NavBarButtonEvent(int id) {
mId = id;
}
@@ -368,7 +368,7 @@
private void logSomePresses(int action, int flags) {
boolean longPressSet = (flags & KeyEvent.FLAG_LONG_PRESS) != 0;
- NavBarActionsEvent uiEvent = NavBarActionsEvent.NONE;
+ NavBarButtonEvent uiEvent = NavBarButtonEvent.NONE;
if (action == MotionEvent.ACTION_UP && mLongClicked) {
return; // don't log the up after a long press
}
@@ -382,21 +382,21 @@
switch(mCode) {
case KeyEvent.KEYCODE_BACK:
uiEvent = longPressSet
- ? NavBarActionsEvent.NAVBAR_BACK_BUTTON_LONGPRESS
- : NavBarActionsEvent.NAVBAR_BACK_BUTTON_TAP;
+ ? NavBarButtonEvent.NAVBAR_BACK_BUTTON_LONGPRESS
+ : NavBarButtonEvent.NAVBAR_BACK_BUTTON_TAP;
break;
case KeyEvent.KEYCODE_HOME:
uiEvent = longPressSet
- ? NavBarActionsEvent.NAVBAR_HOME_BUTTON_LONGPRESS
- : NavBarActionsEvent.NAVBAR_HOME_BUTTON_TAP;
+ ? NavBarButtonEvent.NAVBAR_HOME_BUTTON_LONGPRESS
+ : NavBarButtonEvent.NAVBAR_HOME_BUTTON_TAP;
break;
case KeyEvent.KEYCODE_APP_SWITCH:
uiEvent = longPressSet
- ? NavBarActionsEvent.NAVBAR_OVERVIEW_BUTTON_LONGPRESS
- : NavBarActionsEvent.NAVBAR_OVERVIEW_BUTTON_TAP;
+ ? NavBarButtonEvent.NAVBAR_OVERVIEW_BUTTON_LONGPRESS
+ : NavBarButtonEvent.NAVBAR_OVERVIEW_BUTTON_TAP;
break;
}
- if (uiEvent != NavBarActionsEvent.NONE) {
+ if (uiEvent != NavBarButtonEvent.NONE) {
mUiEventLogger.log(uiEvent);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
index df3748a..512d0f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcher.java
@@ -16,11 +16,15 @@
package com.android.systemui.statusbar.policy;
+import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA;
+import static com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.database.DataSetObserver;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;
@@ -46,8 +50,6 @@
private static final String TAG = "KeyguardUserSwitcher";
private static final boolean ALWAYS_ON = false;
- private static final float USER_SWITCH_ENABLED_ALPHA = 1.0f;
- private static final float USER_SWITCH_DISABLED_ALPHA = 0.38f;
private final Container mUserSwitcherContainer;
private final KeyguardStatusBarView mStatusBarView;
@@ -286,27 +288,34 @@
if (item.picture == null) {
v.bind(name, getDrawable(mContext, item).mutate(), item.resolveId());
} else {
- v.bind(name, item.picture, item.info.id);
+ Drawable drawable = new BitmapDrawable(v.getResources(), item.picture);
+ drawable.setColorFilter(
+ item.isSwitchToEnabled ? null : getDisabledUserAvatarColorFilter());
+ v.bind(name, drawable, item.info.id);
}
- // Disable the icon if switching is disabled
- v.setAvatarEnabled(item.isSwitchToEnabled);
- convertView.setActivated(item.isCurrent);
+ v.setActivated(item.isCurrent);
+ v.setDisabledByAdmin(item.isDisabledByAdmin);
+ v.setEnabled(item.isSwitchToEnabled);
+ v.setAlpha(v.isEnabled() ? USER_SWITCH_ENABLED_ALPHA : USER_SWITCH_DISABLED_ALPHA);
+
if (item.isCurrent) {
- mCurrentUserView = convertView;
+ mCurrentUserView = v;
}
- convertView.setTag(item);
- convertView.setAlpha(
- item.isCurrent || item.isSwitchToEnabled ? USER_SWITCH_ENABLED_ALPHA
- : USER_SWITCH_DISABLED_ALPHA);
- convertView.setEnabled(item.isSwitchToEnabled);
- return convertView;
+ v.setTag(item);
+ return v;
}
private static Drawable getDrawable(Context context,
UserSwitcherController.UserRecord item) {
Drawable drawable = getIconDrawable(context, item);
- int iconColorRes = item.isCurrent ? R.color.kg_user_switcher_selected_avatar_icon_color
- : R.color.kg_user_switcher_avatar_icon_color;
+ int iconColorRes;
+ if (item.isCurrent) {
+ iconColorRes = R.color.kg_user_switcher_selected_avatar_icon_color;
+ } else if (!item.isSwitchToEnabled) {
+ iconColorRes = R.color.GM2_grey_600;
+ } else {
+ iconColorRes = R.color.kg_user_switcher_avatar_icon_color;
+ }
drawable.setTint(context.getResources().getColor(iconColorRes, context.getTheme()));
if (item.isCurrent) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index db00770..270f248 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -31,6 +31,9 @@
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.graphics.Bitmap;
+import android.graphics.ColorFilter;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Handler;
@@ -81,6 +84,9 @@
@Singleton
public class UserSwitcherController implements Dumpable {
+ public static final float USER_SWITCH_ENABLED_ALPHA = 1.0f;
+ public static final float USER_SWITCH_DISABLED_ALPHA = 0.38f;
+
private static final String TAG = "UserSwitcherController";
private static final boolean DEBUG = false;
private static final String SIMPLE_USER_SWITCHER_GLOBAL_SETTING =
@@ -674,6 +680,12 @@
}
}
+ protected static ColorFilter getDisabledUserAvatarColorFilter() {
+ ColorMatrix matrix = new ColorMatrix();
+ matrix.setSaturation(0f); // 0 - grayscale
+ return new ColorMatrixColorFilter(matrix);
+ }
+
protected static Drawable getIconDrawable(Context context, UserRecord item) {
int iconRes;
if (item.isAddUser) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
index 9148683..8b85a0961 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/micdisclosure/AudioRecordingDisclosureBar.java
@@ -29,6 +29,8 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.PixelFormat;
+import android.provider.Settings;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.view.Gravity;
@@ -63,6 +65,9 @@
// CtsSystemUiHostTestCases:TvMicrophoneCaptureIndicatorTest
private static final String LAYOUT_PARAMS_TITLE = "MicrophoneCaptureIndicator";
+ private static final String EXEMPT_PACKAGES_LIST = "sysui_mic_disclosure_exempt";
+ private static final String FORCED_PACKAGES_LIST = "sysui_mic_disclosure_forced";
+
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"STATE_"}, value = {
STATE_NOT_SHOWN,
@@ -134,6 +139,8 @@
mExemptPackages = new ArraySet<>(
Arrays.asList(mContext.getResources().getStringArray(
R.array.audio_recording_disclosure_exempt_apps)));
+ mExemptPackages.addAll(Arrays.asList(getGlobalStringArray(EXEMPT_PACKAGES_LIST)));
+ mExemptPackages.removeAll(Arrays.asList(getGlobalStringArray(FORCED_PACKAGES_LIST)));
mAudioActivityObservers = new AudioActivityObserver[]{
new RecordAudioAppOpObserver(mContext, this),
@@ -141,6 +148,11 @@
};
}
+ private String[] getGlobalStringArray(String setting) {
+ String result = Settings.Global.getString(mContext.getContentResolver(), setting);
+ return TextUtils.isEmpty(result) ? new String[0] : result.split(",");
+ }
+
@UiThread
@Override
public void onAudioActivityStateChange(boolean active, String packageName) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt b/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt
index e905e67..5a2b064 100644
--- a/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt
@@ -32,6 +32,7 @@
import androidx.dynamicanimation.animation.FloatPropertyCompat
import androidx.dynamicanimation.animation.SpringForce
import com.android.systemui.util.animation.PhysicsAnimator
+import kotlin.math.abs
import kotlin.math.hypot
/**
@@ -231,11 +232,11 @@
var flingUnstuckFromTargetMinVelocity = 1000f
/**
- * Sets the maximum velocity above which the object will not stick to the target. Even if the
+ * Sets the maximum X velocity above which the object will not stick to the target. Even if the
* object is dragged through the magnetic field, it will not stick to the target until the
- * velocity is below this value.
+ * horizontal velocity is below this value.
*/
- var stickToTargetMaxVelocity = 2000f
+ var stickToTargetMaxXVelocity = 2000f
/**
* Enable or disable haptic vibration effects when the object interacts with the magnetic field.
@@ -245,9 +246,6 @@
*/
var hapticsEnabled = true
- /** Whether the HAPTIC_FEEDBACK_ENABLED setting is true. */
- private var systemHapticsEnabled = false
-
/** Default spring configuration to use for animating the object into a target. */
var springConfig = PhysicsAnimator.SpringConfig(
SpringForce.STIFFNESS_MEDIUM, SpringForce.DAMPING_RATIO_NO_BOUNCY)
@@ -259,24 +257,7 @@
var flungIntoTargetSpringConfig = springConfig
init {
- val hapticSettingObserver =
- object : ContentObserver(Handler.getMain()) {
- override fun onChange(selfChange: Boolean) {
- systemHapticsEnabled =
- Settings.System.getIntForUser(
- context.contentResolver,
- Settings.System.HAPTIC_FEEDBACK_ENABLED,
- 0,
- UserHandle.USER_CURRENT) != 0
- }
- }
-
- context.contentResolver.registerContentObserver(
- Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_ENABLED),
- true /* notifyForDescendants */, hapticSettingObserver)
-
- // Trigger the observer once to initialize systemHapticsEnabled.
- hapticSettingObserver.onChange(false /* selfChange */)
+ initHapticSettingObserver(context)
}
/**
@@ -383,7 +364,7 @@
// If the object is moving too quickly within the magnetic field, do not stick it. This
// only applies to objects newly stuck to a target. If the object is moved into a new
// target, it wasn't moving at all (since it was stuck to the previous one).
- if (objectNewlyStuckToTarget && hypot(velX, velY) > stickToTargetMaxVelocity) {
+ if (objectNewlyStuckToTarget && abs(velX) > stickToTargetMaxXVelocity) {
return false
}
@@ -623,6 +604,43 @@
companion object {
/**
+ * Whether the HAPTIC_FEEDBACK_ENABLED setting is true.
+ *
+ * We put it in the companion object because we need to register a settings observer and
+ * [MagnetizedObject] doesn't have an obvious lifecycle so we don't have a good time to
+ * remove that observer. Since this settings is shared among all instances we just let all
+ * instances read from this value.
+ */
+ private var systemHapticsEnabled = false
+ private var hapticSettingObserverInitialized = false
+
+ private fun initHapticSettingObserver(context: Context) {
+ if (hapticSettingObserverInitialized) {
+ return
+ }
+
+ val hapticSettingObserver =
+ object : ContentObserver(Handler.getMain()) {
+ override fun onChange(selfChange: Boolean) {
+ systemHapticsEnabled =
+ Settings.System.getIntForUser(
+ context.contentResolver,
+ Settings.System.HAPTIC_FEEDBACK_ENABLED,
+ 0,
+ UserHandle.USER_CURRENT) != 0
+ }
+ }
+
+ context.contentResolver.registerContentObserver(
+ Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_ENABLED),
+ true /* notifyForDescendants */, hapticSettingObserver)
+
+ // Trigger the observer once to initialize systemHapticsEnabled.
+ hapticSettingObserver.onChange(false /* selfChange */)
+ hapticSettingObserverInitialized = true
+ }
+
+ /**
* Magnetizes the given view. Magnetized views are attracted to one or more magnetic
* targets. Magnetic targets attract objects that are dragged near them, and hold them there
* unless they're moved away or released. Releasing objects inside a magnetic target
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
index 74d0610..29d7a52 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.java
@@ -45,6 +45,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -210,6 +211,14 @@
assertTrue((layoutParams.flags & WindowManager.LayoutParams.FLAG_SECURE) != 0);
}
+ @Test
+ public void testLayoutParams_excludesImeInsets() {
+ final IBinder windowToken = mock(IBinder.class);
+ final WindowManager.LayoutParams layoutParams =
+ AuthContainerView.getLayoutParams(windowToken);
+ assertTrue((layoutParams.getFitInsetsTypes() & WindowInsets.Type.ime()) == 0);
+ }
+
private void initializeContainer(int authenticators) {
AuthContainerView.Config config = new AuthContainerView.Config();
config.mContext = mContext;
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 c89f6c2..472b121 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -44,7 +44,6 @@
import android.app.INotificationManager;
import android.app.Notification;
import android.app.PendingIntent;
-import android.content.res.Resources;
import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.face.FaceManager;
import android.os.Handler;
@@ -59,7 +58,7 @@
import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
-import com.android.systemui.SystemUIFactory;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dump.DumpManager;
@@ -70,20 +69,16 @@
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.RankingBuilder;
-import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
-import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.LockscreenLockIconController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
@@ -93,7 +88,6 @@
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.FloatingContentCoordinator;
-import com.android.systemui.util.InjectionInflationController;
import com.google.common.collect.ImmutableList;
@@ -173,23 +167,18 @@
@Mock
ColorExtractor.GradientColors mGradientColors;
@Mock
- private Resources mResources;
- @Mock
private ShadeController mShadeController;
@Mock
- private NotificationRowComponent mNotificationRowComponent;
- @Mock
private NotifPipeline mNotifPipeline;
@Mock
private FeatureFlags mFeatureFlagsOldPipeline;
@Mock
private DumpManager mDumpManager;
@Mock
- private LockscreenLockIconController mLockIconController;
- @Mock
private NotificationShadeWindowView mNotificationShadeWindowView;
+ @Mock
+ private IStatusBarService mStatusBarService;
- private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
private BubbleData mBubbleData;
private TestableLooper mTestableLooper;
@@ -203,23 +192,6 @@
mContext.addMockSystemService(FaceManager.class, mFaceManager);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
- mSuperStatusBarViewFactory = new SuperStatusBarViewFactory(mContext,
- new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()),
- new NotificationRowComponent.Builder() {
- @Override
- public NotificationRowComponent.Builder activatableNotificationView(
- ActivatableNotificationView view) {
- return this;
- }
-
- @Override
- public NotificationRowComponent build() {
- return mNotificationRowComponent;
- }
- },
- mLockIconController);
-
- // Bubbles get added to status bar window view
mNotificationShadeWindowController = new NotificationShadeWindowController(mContext,
mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
mConfigurationController, mKeyguardBypassController, mColorExtractor,
@@ -282,6 +254,7 @@
mDataRepository,
mSysUiState,
mock(INotificationManager.class),
+ mStatusBarService,
mWindowManager);
mBubbleController.setExpandListener(mBubbleExpandListener);
@@ -327,7 +300,7 @@
}
@Test
- public void testPromoteBubble_autoExpand() {
+ public void testPromoteBubble_autoExpand() throws Exception {
mBubbleController.updateBubble(mRow2.getEntry());
mBubbleController.updateBubble(mRow.getEntry());
mBubbleController.removeBubble(
@@ -337,13 +310,19 @@
assertThat(mBubbleData.getOverflowBubbles()).isEqualTo(ImmutableList.of(b));
verify(mNotificationEntryManager, never()).performRemoveNotification(
eq(mRow.getEntry().getSbn()), anyInt());
- assertFalse(mRow.getEntry().isBubble());
+ assertThat(mRow.getEntry().isBubble()).isFalse();
Bubble b2 = mBubbleData.getBubbleInStackWithKey(mRow2.getEntry().getKey());
assertThat(mBubbleData.getSelectedBubble()).isEqualTo(b2);
mBubbleController.promoteBubbleFromOverflow(b);
- assertThat(mBubbleData.getSelectedBubble()).isEqualTo(b);
+
+ assertThat(b.isBubble()).isTrue();
+ assertThat(b.shouldAutoExpand()).isTrue();
+ int flags = Notification.BubbleMetadata.FLAG_AUTO_EXPAND_BUBBLE
+ | Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
+ verify(mStatusBarService, times(1)).onNotificationBubbleChanged(
+ eq(b.getKey()), eq(true), eq(flags));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
index 8224c88e..17022da 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java
@@ -278,7 +278,7 @@
assertBubbleRemoved(mBubbleA1, BubbleController.DISMISS_AGED);
assertOverflowChangedTo(ImmutableList.of(mBubbleA1));
- Bubble bubbleA1 = mBubbleData.getOrCreateBubble(mEntryA1);
+ Bubble bubbleA1 = mBubbleData.getOrCreateBubble(mEntryA1, null /* persistedBubble */);
bubbleA1.markUpdatedAt(7000L);
mBubbleData.notificationEntryUpdated(bubbleA1, false /* suppressFlyout*/,
true /* showInShade */);
@@ -890,7 +890,7 @@
private void sendUpdatedEntryAtTime(NotificationEntry entry, long postTime) {
setPostTime(entry, postTime);
// BubbleController calls this:
- Bubble b = mBubbleData.getOrCreateBubble(entry);
+ Bubble b = mBubbleData.getOrCreateBubble(entry, null /* persistedBubble */);
// And then this
mBubbleData.notificationEntryUpdated(b, false /* suppressFlyout*/,
true /* showInShade */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
index ead95ca1..47cd9bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -55,7 +55,7 @@
import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
-import com.android.systemui.SystemUIFactory;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dump.DumpManager;
@@ -64,14 +64,12 @@
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.RankingBuilder;
-import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
-import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
@@ -87,7 +85,6 @@
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.FloatingContentCoordinator;
-import com.android.systemui.util.InjectionInflationController;
import org.junit.Before;
import org.junit.Test;
@@ -174,8 +171,9 @@
private DumpManager mDumpManager;
@Mock
private LockscreenLockIconController mLockIconController;
+ @Mock
+ private IStatusBarService mStatusBarService;
- private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
private BubbleData mBubbleData;
private TestableLooper mTestableLooper;
@@ -189,22 +187,6 @@
mContext.addMockSystemService(FaceManager.class, mFaceManager);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
- mSuperStatusBarViewFactory = new SuperStatusBarViewFactory(mContext,
- new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()),
- new NotificationRowComponent.Builder() {
- @Override
- public NotificationRowComponent.Builder activatableNotificationView(
- ActivatableNotificationView view) {
- return this;
- }
-
- @Override
- public NotificationRowComponent build() {
- return mNotificationRowComponent;
- }
- },
- mLockIconController);
-
// Bubbles get added to status bar window view
mNotificationShadeWindowController = new NotificationShadeWindowController(mContext,
mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
@@ -257,6 +239,7 @@
mDataRepository,
mSysUiState,
mock(INotificationManager.class),
+ mStatusBarService,
mWindowManager);
mBubbleController.addNotifCallback(mNotifCallback);
mBubbleController.setExpandListener(mBubbleExpandListener);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
index bdb7944..ab49134 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.view.WindowManager;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -59,13 +60,14 @@
BubbleDataRepository dataRepository,
SysUiState sysUiState,
INotificationManager notificationManager,
+ IStatusBarService statusBarService,
WindowManager windowManager) {
super(context,
notificationShadeWindowController, statusBarStateController, shadeController,
data, Runnable::run, configurationController, interruptionStateProvider,
zenModeController, lockscreenUserManager, groupManager, entryManager,
notifPipeline, featureFlags, dumpManager, floatingContentCoordinator,
- dataRepository, sysUiState, notificationManager,
+ dataRepository, sysUiState, notificationManager, statusBarService,
windowManager);
setInflateSynchronously(true);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java
index 536cae4..b7a2633 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/pip/PipAnimationControllerTest.java
@@ -82,7 +82,7 @@
@Test
public void getAnimator_withBounds_returnBoundsAnimator() {
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
- .getAnimator(mLeash, new Rect(), new Rect(), null);
+ .getAnimator(mLeash, new Rect(), new Rect());
assertEquals("Expect ANIM_TYPE_BOUNDS animation",
animator.getAnimationType(), PipAnimationController.ANIM_TYPE_BOUNDS);
@@ -94,12 +94,12 @@
final Rect endValue1 = new Rect(100, 100, 200, 200);
final Rect endValue2 = new Rect(200, 200, 300, 300);
final PipAnimationController.PipTransitionAnimator oldAnimator = mPipAnimationController
- .getAnimator(mLeash, startValue, endValue1, null);
+ .getAnimator(mLeash, startValue, endValue1);
oldAnimator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
oldAnimator.start();
final PipAnimationController.PipTransitionAnimator newAnimator = mPipAnimationController
- .getAnimator(mLeash, startValue, endValue2, null);
+ .getAnimator(mLeash, startValue, endValue2);
assertEquals("getAnimator with same type returns same animator",
oldAnimator, newAnimator);
@@ -129,7 +129,7 @@
final Rect endValue1 = new Rect(100, 100, 200, 200);
final Rect endValue2 = new Rect(200, 200, 300, 300);
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
- .getAnimator(mLeash, startValue, endValue1, null);
+ .getAnimator(mLeash, startValue, endValue1);
animator.updateEndValue(endValue2);
@@ -141,7 +141,7 @@
final Rect startValue = new Rect(0, 0, 100, 100);
final Rect endValue = new Rect(100, 100, 200, 200);
final PipAnimationController.PipTransitionAnimator animator = mPipAnimationController
- .getAnimator(mLeash, startValue, endValue, null);
+ .getAnimator(mLeash, startValue, endValue);
animator.setSurfaceControlTransactionFactory(DummySurfaceControlTx::new);
animator.setPipAnimationCallback(mPipAnimationCallback);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
index 8a8d227..e502459 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
@@ -29,6 +29,7 @@
import androidx.test.filters.SmallTest;
+import com.android.internal.logging.UiEventLogger;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
@@ -53,6 +54,8 @@
private ActivityStarter mActivityStarter;
@Mock
private QSTileHost mHost;
+ @Mock
+ private UiEventLogger mUiEventLogger;
private TestableLooper mTestableLooper;
private ScreenRecordTile mTile;
@@ -68,7 +71,7 @@
when(mHost.getContext()).thenReturn(mContext);
- mTile = new ScreenRecordTile(mHost, mController, mActivityStarter);
+ mTile = new ScreenRecordTile(mHost, mController, mActivityStarter, mUiEventLogger);
}
// Test that the tile is inactive and labeled correctly when the controller is neither starting
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
new file mode 100644
index 0000000..283a47c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenrecord;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Intent;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.concurrent.Executor;
+
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+public class RecordingServiceTest extends SysuiTestCase {
+
+ @Mock
+ private UiEventLogger mUiEventLogger;
+ @Mock
+ private RecordingController mController;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private ScreenMediaRecorder mScreenMediaRecorder;
+ @Mock
+ private Notification mNotification;
+ @Mock
+ private Executor mExecutor;
+
+ private RecordingService mRecordingService;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mRecordingService = Mockito.spy(new RecordingService(mController, mExecutor, mUiEventLogger,
+ mNotificationManager));
+
+ // Return actual context info
+ doReturn(mContext).when(mRecordingService).getApplicationContext();
+ doReturn(mContext.getUserId()).when(mRecordingService).getUserId();
+ doReturn(mContext.getPackageName()).when(mRecordingService).getPackageName();
+ doReturn(mContext.getContentResolver()).when(mRecordingService).getContentResolver();
+
+ // Mock notifications
+ doNothing().when(mRecordingService).createRecordingNotification();
+ doReturn(mNotification).when(mRecordingService).createProcessingNotification();
+ doReturn(mNotification).when(mRecordingService).createSaveNotification(any());
+
+ doNothing().when(mRecordingService).startForeground(anyInt(), any());
+ doReturn(mScreenMediaRecorder).when(mRecordingService).getRecorder();
+ }
+
+ @Test
+ public void testLogStartRecording() {
+ Intent startIntent = RecordingService.getStartIntent(mContext, 0, 0, false);
+ mRecordingService.onStartCommand(startIntent, 0, 0);
+
+ verify(mUiEventLogger, times(1)).log(Events.ScreenRecordEvent.SCREEN_RECORD_START);
+ }
+
+ @Test
+ public void testLogStopFromQsTile() {
+ Intent stopIntent = RecordingService.getStopIntent(mContext);
+ mRecordingService.onStartCommand(stopIntent, 0, 0);
+
+ // Verify that we log the correct event
+ verify(mUiEventLogger, times(1)).log(Events.ScreenRecordEvent.SCREEN_RECORD_END_QS_TILE);
+ verify(mUiEventLogger, times(0))
+ .log(Events.ScreenRecordEvent.SCREEN_RECORD_END_NOTIFICATION);
+ }
+
+ @Test
+ public void testLogStopFromNotificationIntent() {
+ Intent stopIntent = RecordingService.getNotificationIntent(mContext);
+ mRecordingService.onStartCommand(stopIntent, 0, 0);
+
+ // Verify that we log the correct event
+ verify(mUiEventLogger, times(1))
+ .log(Events.ScreenRecordEvent.SCREEN_RECORD_END_NOTIFICATION);
+ verify(mUiEventLogger, times(0)).log(Events.ScreenRecordEvent.SCREEN_RECORD_END_QS_TILE);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
index 78e9b33..2b12c22 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/HighPriorityProviderTest.java
@@ -38,6 +38,7 @@
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
import org.junit.Before;
import org.junit.Test;
@@ -45,16 +46,22 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
+import java.util.Arrays;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class HighPriorityProviderTest extends SysuiTestCase {
@Mock private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
+ @Mock private NotificationGroupManager mGroupManager;
private HighPriorityProvider mHighPriorityProvider;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mHighPriorityProvider = new HighPriorityProvider(mPeopleNotificationIdentifier);
+ mHighPriorityProvider = new HighPriorityProvider(
+ mPeopleNotificationIdentifier,
+ mGroupManager);
}
@Test
@@ -166,6 +173,22 @@
}
@Test
+ public void testIsHighPriority_checkChildrenToCalculatePriority() {
+ // GIVEN: a summary with low priority has a highPriorityChild and a lowPriorityChild
+ final NotificationEntry summary = createNotifEntry(false);
+ final NotificationEntry lowPriorityChild = createNotifEntry(false);
+ final NotificationEntry highPriorityChild = createNotifEntry(true);
+ when(mGroupManager.isGroupSummary(summary.getSbn())).thenReturn(true);
+ when(mGroupManager.getChildren(summary.getSbn())).thenReturn(
+ new ArrayList<>(Arrays.asList(lowPriorityChild, highPriorityChild)));
+
+ // THEN the summary is high priority since it has a high priority child
+ assertTrue(mHighPriorityProvider.isHighPriority(summary));
+ }
+
+ // Tests below here are only relevant to the NEW notification pipeline which uses GroupEntry
+
+ @Test
public void testIsHighPriority_summaryUpdated() {
// GIVEN a GroupEntry with a lowPrioritySummary and no children
final GroupEntry parentEntry = new GroupEntry("test_group_key");
@@ -186,7 +209,7 @@
}
@Test
- public void testIsHighPriority_checkChildrenToCalculatePriority() {
+ public void testIsHighPriority_checkChildrenToCalculatePriorityOf() {
// GIVEN:
// GroupEntry = parentEntry, summary = lowPrioritySummary
// NotificationEntry = lowPriorityChild
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
index 1c47131..82a7774 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
@@ -77,7 +77,8 @@
mock(NotificationEntryManagerLogger::class.java),
sectionsManager,
personNotificationIdentifier,
- HighPriorityProvider(personNotificationIdentifier)
+ HighPriorityProvider(personNotificationIdentifier,
+ mock(NotificationGroupManager::class.java))
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java
index f327967..43aa8fe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/PartialConversationInfoTest.java
@@ -25,6 +25,7 @@
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
@@ -162,6 +163,7 @@
@Test
public void testBindNotification_SetsName() {
+ when(mMockPackageManager.getApplicationLabel(any())).thenReturn("Package");
mInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
@@ -174,15 +176,13 @@
true,
false);
final TextView textView = mInfo.findViewById(R.id.name);
- assertTrue(textView.getText().toString().contains("title"));
+ assertTrue(textView.getText().toString().equals("Package"));
}
+
@Test
- public void testBindNotification_groupSetsPackageIcon() {
- mEntry.getSbn().getNotification().extras.putBoolean(EXTRA_IS_GROUP_CONVERSATION, true);
- final Drawable iconDrawable = mock(Drawable.class);
- when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
- .thenReturn(iconDrawable);
+ public void testBindNotification_setsIcon() {
+ when(mMockPackageManager.getApplicationIcon((ApplicationInfo) any())).thenReturn(mDrawable);
mInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
@@ -194,34 +194,7 @@
null,
true,
false);
- final ImageView iconView = mInfo.findViewById(R.id.conversation_icon);
- assertEquals(iconDrawable, iconView.getDrawable());
- }
-
- @Test
- public void testBindNotification_notGroupSetsMessageIcon() {
- Notification n = new Notification.Builder(mContext, TEST_CHANNEL_NAME)
- .setStyle(new Notification.MessagingStyle(
- new Person.Builder().setName("me").build())
- .addMessage(new Notification.MessagingStyle.Message("hello", 0,
- new Person.Builder().setName("friend").setIcon(mIcon).build())))
- .build();
- mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
- n, UserHandle.CURRENT, null, 0);
- mEntry.setSbn(mSbn);
- mEntry.getSbn().getNotification().extras.putBoolean(EXTRA_IS_GROUP_CONVERSATION, false);
- mInfo.bindNotification(
- mMockPackageManager,
- mMockINotificationManager,
- mChannelEditorDialogController,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mNotificationChannelSet,
- mEntry,
- null,
- true,
- false);
- final ImageView iconView = mInfo.findViewById(R.id.conversation_icon);
+ final ImageView iconView = mInfo.findViewById(R.id.icon);
assertEquals(mDrawable.hashCode() + "", mDrawable, iconView.getDrawable());
}
@@ -270,64 +243,6 @@
}
@Test
- public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
- mInfo.bindNotification(
- mMockPackageManager,
- mMockINotificationManager,
- mChannelEditorDialogController,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mNotificationChannelSet,
- mEntry,
- null,
- true,
- false);
- final TextView groupNameView = mInfo.findViewById(R.id.group_name);
- assertEquals(GONE, groupNameView.getVisibility());
- }
-
- @Test
- public void testBindNotification_SetsGroupNameIfNonNull() throws Exception {
- mNotificationChannel.setGroup("test_group_id");
- final NotificationChannelGroup notificationChannelGroup =
- new NotificationChannelGroup("test_group_id", "Test Group Name");
- when(mMockINotificationManager.getNotificationChannelGroupForPackage(
- eq("test_group_id"), eq(TEST_PACKAGE_NAME), eq(TEST_UID)))
- .thenReturn(notificationChannelGroup);
- mInfo.bindNotification(
- mMockPackageManager,
- mMockINotificationManager,
- mChannelEditorDialogController,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mNotificationChannelSet,
- mEntry,
- null,
- true,
- false);
- final TextView groupNameView = mInfo.findViewById(R.id.group_name);
- assertEquals(View.VISIBLE, groupNameView.getVisibility());
- assertEquals("Test Group Name", groupNameView.getText());
- }
-
- @Test
- public void testBindNotification_SetsTextChannelName() {
- mInfo.bindNotification(
- mMockPackageManager,
- mMockINotificationManager,
- mChannelEditorDialogController,
- TEST_PACKAGE_NAME,
- mNotificationChannel,
- mNotificationChannelSet,
- mEntry,
- null,
- true,
- false);
- final TextView textView = mInfo.findViewById(R.id.parent_channel_name);
- assertEquals(TEST_CHANNEL_NAME, textView.getText());
- }
-
- @Test
public void testBindNotification_SetsOnClickListenerForSettings() {
final CountDownLatch latch = new CountDownLatch(1);
mInfo.bindNotification(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index a77f8c6..00cbddc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -21,6 +21,8 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
+import static com.android.systemui.statusbar.phone.NavigationBarFragment.NavBarActionEvent.NAVBAR_ASSIST_LONGPRESS;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -28,6 +30,7 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -59,6 +62,7 @@
import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
import com.android.systemui.Dependency;
import com.android.systemui.SysuiBaseFragmentTest;
import com.android.systemui.SysuiTestableContext;
@@ -105,6 +109,8 @@
private Recents mRecents;
@Mock
private SystemActions mSystemActions;
+ @Mock
+ private UiEventLogger mUiEventLogger;
private AccessibilityManagerWrapper mAccessibilityWrapper =
new AccessibilityManagerWrapper(mContext) {
@@ -187,6 +193,8 @@
mFragments.dispatchResume();
processAllMessages();
navigationBarFragment.onHomeLongClick(navigationBarFragment.getView());
+
+ verify(mUiEventLogger, times(1)).log(NAVBAR_ASSIST_LONGPRESS);
}
@Test
@@ -242,6 +250,7 @@
protected Fragment instantiate(Context context, String className, Bundle arguments) {
DeviceProvisionedController deviceProvisionedController =
mock(DeviceProvisionedController.class);
+ when(deviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
assertNotNull(mAccessibilityWrapper);
return new NavigationBarFragment(
context.getDisplayId() == DEFAULT_DISPLAY ? mAccessibilityWrapper
@@ -261,7 +270,8 @@
mock(ShadeController.class),
mock(NotificationRemoteInputManager.class),
mock(SystemActions.class),
- mHandler);
+ mHandler,
+ mUiEventLogger);
}
private class HostCallbacksForExternalDisplay extends
@@ -319,6 +329,7 @@
mock(LightBarTransitionsController.class));
when(view.getRotationButtonController()).thenReturn(
mock(RotationButtonController.class));
+ when(view.isRecentsButtonVisible()).thenReturn(true);
return view;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java
index 5e9d592..d52d686 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyButtonViewTest.java
@@ -23,12 +23,12 @@
import static android.view.KeyEvent.KEYCODE_BACK;
import static android.view.KeyEvent.KEYCODE_HOME;
-import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarActionsEvent.NAVBAR_BACK_BUTTON_LONGPRESS;
-import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarActionsEvent.NAVBAR_BACK_BUTTON_TAP;
-import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarActionsEvent.NAVBAR_HOME_BUTTON_LONGPRESS;
-import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarActionsEvent.NAVBAR_HOME_BUTTON_TAP;
-import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarActionsEvent.NAVBAR_OVERVIEW_BUTTON_LONGPRESS;
-import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarActionsEvent.NAVBAR_OVERVIEW_BUTTON_TAP;
+import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarButtonEvent.NAVBAR_BACK_BUTTON_LONGPRESS;
+import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarButtonEvent.NAVBAR_BACK_BUTTON_TAP;
+import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarButtonEvent.NAVBAR_HOME_BUTTON_LONGPRESS;
+import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarButtonEvent.NAVBAR_HOME_BUTTON_TAP;
+import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarButtonEvent.NAVBAR_OVERVIEW_BUTTON_LONGPRESS;
+import static com.android.systemui.statusbar.policy.KeyButtonView.NavBarButtonEvent.NAVBAR_OVERVIEW_BUTTON_TAP;
import static junit.framework.Assert.assertEquals;
@@ -140,11 +140,11 @@
}
private void checkmetrics(int code, int action, int flag,
- KeyButtonView.NavBarActionsEvent expected) {
+ KeyButtonView.NavBarButtonEvent expected) {
mKeyButtonView.setCode(code);
mKeyButtonView.sendEvent(action, flag);
if (expected == null) {
- verify(mUiEventLogger, never()).log(any(KeyButtonView.NavBarActionsEvent.class));
+ verify(mUiEventLogger, never()).log(any(KeyButtonView.NavBarButtonEvent.class));
} else {
verify(mUiEventLogger, times(1)).log(expected);
}
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index d07a70c..32e2b04 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -25,7 +25,7 @@
],
static_libs: [
"androidx.annotation_annotation",
- "netd_aidl_interface-V3-java",
+ "netd_aidl_interface-java",
"netlink-client",
"networkstack-aidl-interfaces-java",
"android.hardware.tetheroffload.config-V1.0-java",
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_select.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_select.xml
index 4e265fd..0f37561 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_select.xml
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_select.xml
@@ -18,15 +18,6 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
- android:fillColor="#FF000000"
- android:pathData="M11.25,1h1.5v3h-1.5z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M15.5983,5.3402l2.1213,-2.1213l1.0606,1.0606l-2.1213,2.1213z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M5.2187,4.2803l1.0606,-1.0606l2.1213,2.1213l-1.0606,1.0606z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M15.5,12.5l-1.25,0V8.12C14.25,6.95 13.3,6 12.12,6S10,6.95 10,8.12v7.9L8.03,15.5c-0.39,-0.1 -1.23,-0.36 -2.56,0.97c-0.29,0.29 -0.29,0.75 -0.01,1.05l3.79,3.98c0,0 0,0 0,0.01c1.37,1.41 3.28,1.51 4.04,1.49l2.2,0c2.12,0.06 5.25,-1.01 5.25,-5.25C20.75,13.19 17.23,12.46 15.5,12.5zM15.5,21.5l-2.25,0c-0.44,0.01 -1.93,-0.02 -2.92,-1.03l-3.27,-3.43c0.17,-0.1 0.38,-0.13 0.58,-0.08l2.91,0.78c0.47,0.12 0.94,-0.23 0.94,-0.72V8.12c0,-0.34 0.28,-0.62 0.62,-0.62s0.62,0.28 0.62,0.62v5.12c0,0.41 0.33,0.75 0.75,0.75l2.05,0c1.26,-0.03 3.7,0.37 3.7,3.75C19.25,21.14 16.78,21.53 15.5,21.5z"/>
+ android:fillColor="@android:color/white"
+ android:pathData="M18.04,13.71c-0.71,-0.77 -1.71,-1.21 -2.76,-1.21h-1.15V8.12C14.13,6.95 13.18,6 12,6S9.88,6.95 9.88,8.12v7.9l-1.44,-0.38c-1.1,-0.29 -2.28,0.02 -3.09,0.83l-0.52,0.52L10.56,23h7.92l0.54,-6.44C19.1,15.52 18.75,14.48 18.04,13.71zM17.1,21.5h-5.9l-4.16,-4.37c0.32,-0.11 0.68,-0.13 1.01,-0.04l3.33,0.89V8.12c0,-0.34 0.28,-0.62 0.62,-0.62s0.62,0.28 0.62,0.62V14h2.65c0.64,0 1.22,0.26 1.66,0.73c0.43,0.47 0.64,1.08 0.59,1.71L17.1,21.5zM2.81,8.25h0.38c0.31,0 0.56,0.26 0.56,0.56v0.38c0,0.31 -0.26,0.56 -0.56,0.56H2.81c-0.31,0 -0.56,-0.26 -0.56,-0.56V8.81C2.25,8.51 2.51,8.25 2.81,8.25zM5.81,8.25h0.38c0.31,0 0.56,0.26 0.56,0.56v0.38c0,0.31 -0.26,0.56 -0.56,0.56H5.81c-0.31,0 -0.56,-0.26 -0.56,-0.56V8.81C5.25,8.51 5.51,8.25 5.81,8.25zM17.81,8.25h0.38c0.31,0 0.56,0.26 0.56,0.56v0.38c0,0.31 -0.26,0.56 -0.56,0.56h-0.38c-0.31,0 -0.56,-0.26 -0.56,-0.56V8.81C17.25,8.51 17.5,8.25 17.81,8.25zM20.81,8.25h0.38c0.31,0 0.56,0.26 0.56,0.56v0.38c0,0.31 -0.26,0.56 -0.56,0.56h-0.38c-0.31,0 -0.56,-0.26 -0.56,-0.56V8.81C20.25,8.51 20.5,8.25 20.81,8.25zM2.81,5.25h0.38c0.31,0 0.56,0.26 0.56,0.56v0.38c0,0.31 -0.26,0.56 -0.56,0.56H2.81c-0.31,0 -0.56,-0.26 -0.56,-0.56V5.81C2.25,5.5 2.51,5.25 2.81,5.25zM20.81,5.25h0.38c0.31,0 0.56,0.26 0.56,0.56v0.38c0,0.31 -0.26,0.56 -0.56,0.56h-0.38c-0.31,0 -0.56,-0.26 -0.56,-0.56V5.81C20.25,5.5 20.5,5.25 20.81,5.25zM2.81,2.25h0.38c0.31,0 0.56,0.26 0.56,0.56v0.38c0,0.31 -0.26,0.56 -0.56,0.56H2.81c-0.31,0 -0.56,-0.26 -0.56,-0.56V2.81C2.25,2.51 2.51,2.25 2.81,2.25zM5.81,2.25h0.38c0.31,0 0.56,0.26 0.56,0.56v0.38c0,0.31 -0.26,0.56 -0.56,0.56H5.81c-0.31,0 -0.56,-0.26 -0.56,-0.56V2.81C5.25,2.51 5.51,2.25 5.81,2.25zM8.81,2.25h0.38c0.31,0 0.56,0.26 0.56,0.56v0.38c0,0.31 -0.26,0.56 -0.56,0.56H8.81c-0.31,0 -0.56,-0.26 -0.56,-0.56V2.81C8.25,2.51 8.51,2.25 8.81,2.25zM11.81,2.25h0.38c0.31,0 0.56,0.26 0.56,0.56v0.38c0,0.31 -0.26,0.56 -0.56,0.56h-0.38c-0.31,0 -0.56,-0.26 -0.56,-0.56V2.81C11.25,2.51 11.51,2.25 11.81,2.25zM14.81,2.25h0.38c0.31,0 0.56,0.26 0.56,0.56v0.38c0,0.31 -0.26,0.56 -0.56,0.56h-0.38c-0.31,0 -0.56,-0.26 -0.56,-0.56V2.81C14.25,2.51 14.51,2.25 14.81,2.25zM17.81,2.25h0.38c0.31,0 0.56,0.26 0.56,0.56v0.38c0,0.31 -0.26,0.56 -0.56,0.56h-0.38c-0.31,0 -0.56,-0.26 -0.56,-0.56V2.81C17.25,2.51 17.5,2.25 17.81,2.25zM17.81,2.25h0.38c0.31,0 0.56,0.26 0.56,0.56v0.38c0,0.31 -0.26,0.56 -0.56,0.56h-0.38c-0.31,0 -0.56,-0.26 -0.56,-0.56V2.81C17.25,2.51 17.5,2.25 17.81,2.25zM20.81,2.25h0.38c0.31,0 0.56,0.26 0.56,0.56v0.38c0,0.31 -0.26,0.56 -0.56,0.56h-0.38c-0.31,0 -0.56,-0.26 -0.56,-0.56V2.81C20.25,2.51 20.5,2.25 20.81,2.25z"/>
</vector>
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_select.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_select.xml
index df4525d..51d4a11 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_select.xml
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_select.xml
@@ -18,15 +18,6 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
- android:fillColor="#FF000000"
- android:pathData="M17.59,5.83l0.71,-0.71c0.39,-0.39 0.39,-1.02 0,-1.41l0,0c-0.39,-0.39 -1.02,-0.39 -1.41,0l-0.71,0.71c-0.39,0.39 -0.39,1.02 0,1.41C16.56,6.21 17.2,6.21 17.59,5.83z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M12,4c0.55,0 1,-0.45 1,-1V2c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1v1C11,3.55 11.45,4 12,4z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M6.42,5.83c0.39,0.39 1.02,0.39 1.41,0c0.39,-0.39 0.39,-1.02 0,-1.41L7.12,3.71c-0.39,-0.39 -1.02,-0.39 -1.41,0l0,0c-0.39,0.39 -0.39,1.02 0,1.41L6.42,5.83z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M17.95,14.43l-3.23,-1.61c-0.42,-0.21 -0.88,-0.32 -1.34,-0.32H13v-5C13,6.67 12.33,6 11.5,6C10.67,6 10,6.67 10,7.5v9.12c0,0.32 -0.29,0.55 -0.6,0.49l-2.84,-0.6c-0.37,-0.08 -0.76,0.04 -1.03,0.31c-0.43,0.44 -0.43,1.14 0.01,1.58l3.71,3.71C9.81,22.68 10.58,23 11.37,23h4.82c1.49,0 2.76,-1.1 2.97,-2.58l0.41,-2.89C19.76,16.26 19.1,15.01 17.95,14.43z"/>
+ android:fillColor="@android:color/white"
+ android:pathData="M19.09,14.75L15,12.71c-0.28,-0.14 -0.58,-0.21 -0.89,-0.21H13.5v-5C13.5,6.67 12.83,6 12,6s-1.5,0.67 -1.5,1.5v9.74L7,16.5c-0.33,-0.07 -0.68,0.03 -0.92,0.28l-0.13,0.13c-0.39,0.39 -0.38,1.02 0,1.41l4.09,4.09c0.38,0.38 0.89,0.59 1.42,0.59h6.1c1,0 1.84,-0.73 1.98,-1.72l0.63,-4.46C20.3,15.97 19.86,15.14 19.09,14.75zM2.62,9.75h0.75c0.21,0 0.38,-0.17 0.38,-0.38V8.62c0,-0.21 -0.17,-0.38 -0.38,-0.38H2.62c-0.21,0 -0.38,0.16 -0.38,0.38v0.75C2.25,9.58 2.42,9.75 2.62,9.75zM5.62,9.75h0.75c0.21,0 0.38,-0.17 0.38,-0.38V8.62c0,-0.21 -0.17,-0.38 -0.38,-0.38H5.62c-0.21,0 -0.38,0.16 -0.38,0.38v0.75C5.25,9.58 5.41,9.75 5.62,9.75zM17.62,9.75h0.75c0.21,0 0.38,-0.17 0.38,-0.38V8.62c0,-0.21 -0.17,-0.38 -0.38,-0.38h-0.75c-0.21,0 -0.38,0.16 -0.38,0.38v0.75C17.25,9.58 17.42,9.75 17.62,9.75zM20.62,9.75h0.75c0.21,0 0.38,-0.17 0.38,-0.38V8.62c0,-0.21 -0.17,-0.38 -0.38,-0.38h-0.75c-0.21,0 -0.38,0.16 -0.38,0.38v0.75C20.25,9.58 20.42,9.75 20.62,9.75zM2.62,6.75h0.75c0.21,0 0.38,-0.16 0.38,-0.38V5.62c0,-0.21 -0.17,-0.38 -0.38,-0.38H2.62c-0.21,0 -0.38,0.17 -0.38,0.38v0.75C2.25,6.58 2.42,6.75 2.62,6.75zM20.62,6.75h0.75c0.21,0 0.38,-0.16 0.38,-0.38V5.62c0,-0.21 -0.17,-0.38 -0.38,-0.38h-0.75c-0.21,0 -0.38,0.17 -0.38,0.38v0.75C20.25,6.58 20.42,6.75 20.62,6.75zM2.62,3.75h0.75c0.21,0 0.38,-0.17 0.38,-0.38V2.62c0,-0.21 -0.17,-0.38 -0.38,-0.38H2.62c-0.21,0 -0.38,0.17 -0.38,0.38v0.75C2.25,3.58 2.42,3.75 2.62,3.75zM5.62,3.75h0.75c0.21,0 0.38,-0.17 0.38,-0.38V2.62c0,-0.21 -0.16,-0.38 -0.38,-0.38H5.62c-0.21,0 -0.38,0.17 -0.38,0.38v0.75C5.25,3.58 5.41,3.75 5.62,3.75zM8.62,3.75h0.75c0.21,0 0.38,-0.17 0.38,-0.38V2.62c0,-0.21 -0.16,-0.38 -0.38,-0.38H8.62c-0.21,0 -0.38,0.17 -0.38,0.38v0.75C8.25,3.58 8.41,3.75 8.62,3.75zM14.62,3.75h0.75c0.21,0 0.38,-0.17 0.38,-0.38V2.62c0,-0.21 -0.16,-0.38 -0.38,-0.38h-0.75c-0.21,0 -0.38,0.17 -0.38,0.38v0.75C14.25,3.58 14.41,3.75 14.62,3.75zM17.62,3.75h0.75c0.21,0 0.38,-0.17 0.38,-0.38V2.62c0,-0.21 -0.17,-0.38 -0.38,-0.38h-0.75c-0.21,0 -0.38,0.17 -0.38,0.38v0.75C17.25,3.58 17.42,3.75 17.62,3.75zM20.62,3.75h0.75c0.21,0 0.38,-0.17 0.38,-0.38V2.62c0,-0.21 -0.17,-0.38 -0.38,-0.38h-0.75c-0.21,0 -0.38,0.17 -0.38,0.38v0.75C20.25,3.58 20.42,3.75 20.62,3.75zM11.62,3.75h0.75c0.21,0 0.38,-0.17 0.38,-0.38V2.62c0,-0.21 -0.16,-0.38 -0.38,-0.38h-0.75c-0.21,0 -0.38,0.17 -0.38,0.38v0.75C11.25,3.58 11.41,3.75 11.62,3.75z"/>
</vector>
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_select.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_select.xml
index b699a44..7bd92ef 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_select.xml
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_select.xml
@@ -17,16 +17,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
- <path
- android:fillColor="#FF000000"
- android:pathData="M16.19,12.5h-1.94V8.12C14.25,6.95 13.3,6 12.12,6S10,6.95 10,8.12v7.9l-3.22,-0.86l-1.82,1.82L10.68,23h8.6l1.57,-7.96L16.19,12.5zM18.04,21.5h-6.72l-4.27,-4.49l0.18,-0.18l4.28,1.14V8.12c0,-0.34 0.28,-0.62 0.62,-0.62s0.62,0.28 0.62,0.62V14h3.06l3.35,1.83L18.04,21.5z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M11.25,1h1.5v3h-1.5z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M15.5983,5.3402l2.1213,-2.1213l1.0606,1.0606l-2.1213,2.1213z"/>
- <path
- android:fillColor="#FF000000"
- android:pathData="M5.2187,4.2803l1.0606,-1.0606l2.1213,2.1213l-1.0606,1.0606z"/>
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18.46,14.17l-4.33,-1.46V8.12C14.13,6.95 13.18,6 12,6S9.88,6.95 9.88,8.12v7.9l-2.3,-0.61c-0.57,-0.15 -1.18,0.01 -1.6,0.43c-0.64,0.64 -0.66,1.66 -0.03,2.32l3.79,3.99c0.52,0.54 1.24,0.85 1.99,0.85h5.16c1.31,0 2.44,-0.93 2.7,-2.22l0.69,-3.48C20.54,15.95 19.76,14.6 18.46,14.17zM18.81,17.01l-0.69,3.48c-0.11,0.58 -0.63,1.01 -1.23,1.01h-5.16c-0.34,0 -0.67,-0.14 -0.91,-0.39l-3.8,-3.99c-0.06,-0.06 -0.06,-0.16 0,-0.23c0.03,-0.03 0.07,-0.05 0.11,-0.05c0.01,0 0.03,0 0.04,0.01l3.24,0.86c0.22,0.06 0.46,0.01 0.65,-0.13c0.18,-0.14 0.29,-0.36 0.29,-0.59V8.12c0,-0.34 0.28,-0.62 0.62,-0.62s0.62,0.28 0.62,0.62v5.12c0,0.32 0.21,0.61 0.51,0.71l4.84,1.63C18.57,15.79 18.93,16.4 18.81,17.01zM3.38,8.25H2.62c-0.21,0 -0.38,0.16 -0.38,0.38v0.75c0,0.21 0.16,0.38 0.38,0.38h0.75c0.21,0 0.38,-0.17 0.38,-0.38V8.62C3.75,8.41 3.59,8.25 3.38,8.25zM6.38,8.25H5.62c-0.21,0 -0.38,0.16 -0.38,0.38v0.75c0,0.21 0.16,0.38 0.38,0.38h0.75c0.21,0 0.38,-0.17 0.38,-0.38V8.62C6.75,8.41 6.59,8.25 6.38,8.25zM18.38,8.25h-0.75c-0.21,0 -0.38,0.16 -0.38,0.38v0.75c0,0.21 0.16,0.38 0.38,0.38h0.75c0.21,0 0.38,-0.17 0.38,-0.38V8.62C18.75,8.41 18.59,8.25 18.38,8.25zM21.38,8.25h-0.75c-0.21,0 -0.38,0.16 -0.38,0.38v0.75c0,0.21 0.16,0.38 0.38,0.38h0.75c0.21,0 0.38,-0.17 0.38,-0.38V8.62C21.75,8.41 21.59,8.25 21.38,8.25zM3.38,5.25H2.62c-0.21,0 -0.38,0.16 -0.38,0.38v0.75c0,0.21 0.16,0.38 0.38,0.38h0.75c0.21,0 0.38,-0.17 0.38,-0.38V5.62C3.75,5.41 3.59,5.25 3.38,5.25zM21.38,5.25h-0.75c-0.21,0 -0.38,0.16 -0.38,0.38v0.75c0,0.21 0.16,0.38 0.38,0.38h0.75c0.21,0 0.38,-0.17 0.38,-0.38V5.62C21.75,5.41 21.59,5.25 21.38,5.25zM3.38,2.25H2.62c-0.21,0 -0.38,0.17 -0.38,0.38v0.75c0,0.21 0.16,0.38 0.38,0.38h0.75c0.21,0 0.38,-0.17 0.38,-0.38V2.62C3.75,2.42 3.59,2.25 3.38,2.25zM6.38,2.25H5.62c-0.21,0 -0.38,0.17 -0.38,0.38v0.75c0,0.21 0.16,0.38 0.38,0.38h0.75c0.21,0 0.38,-0.17 0.38,-0.38V2.62C6.75,2.42 6.59,2.25 6.38,2.25zM9.38,2.25H8.62c-0.21,0 -0.38,0.17 -0.38,0.38v0.75c0,0.21 0.16,0.38 0.38,0.38h0.75c0.21,0 0.38,-0.17 0.38,-0.38V2.62C9.75,2.42 9.59,2.25 9.38,2.25zM12.38,2.25h-0.75c-0.21,0 -0.38,0.17 -0.38,0.38v0.75c0,0.21 0.16,0.38 0.38,0.38h0.75c0.21,0 0.38,-0.17 0.38,-0.38V2.62C12.75,2.42 12.59,2.25 12.38,2.25zM15.38,2.25h-0.75c-0.21,0 -0.38,0.17 -0.38,0.38v0.75c0,0.21 0.16,0.38 0.38,0.38h0.75c0.21,0 0.38,-0.17 0.38,-0.38V2.62C15.75,2.42 15.59,2.25 15.38,2.25zM18.38,2.25h-0.75c-0.21,0 -0.38,0.17 -0.38,0.38v0.75c0,0.21 0.16,0.38 0.38,0.38h0.75c0.21,0 0.38,-0.17 0.38,-0.38V2.62C18.75,2.42 18.59,2.25 18.38,2.25zM18.38,2.25h-0.75c-0.21,0 -0.38,0.17 -0.38,0.38v0.75c0,0.21 0.16,0.38 0.38,0.38h0.75c0.21,0 0.38,-0.17 0.38,-0.38V2.62C18.75,2.42 18.59,2.25 18.38,2.25zM21.38,2.25h-0.75c-0.21,0 -0.38,0.17 -0.38,0.38v0.75c0,0.21 0.16,0.38 0.38,0.38h0.75c0.21,0 0.38,-0.17 0.38,-0.38V2.62C21.75,2.42 21.59,2.25 21.38,2.25z" />
</vector>
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 642526d..a9a0ab6 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2715,7 +2715,9 @@
final ViewState currentView = mViewStates.get(mCurrentViewId);
currentView.maybeCallOnFillReady(flags);
}
- } else if (viewState.id.equals(this.mCurrentViewId)
+ }
+
+ if (viewState.id.equals(this.mCurrentViewId)
&& (viewState.getState() & ViewState.STATE_INLINE_SHOWN) != 0) {
if ((viewState.getState() & ViewState.STATE_INLINE_DISABLED) != 0) {
mInlineSessionController.disableFilterMatching(viewState.id);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 8eb401a..1ce3dfe 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -157,7 +157,6 @@
import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
import com.android.server.pm.Installer;
-import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.storage.AppFuseBridge;
import com.android.server.storage.StorageSessionController;
import com.android.server.storage.StorageSessionController.ExternalStorageServiceException;
@@ -3343,15 +3342,23 @@
public void fixupAppDir(String path) {
final Matcher matcher = KNOWN_APP_DIR_PATHS.matcher(path);
if (matcher.matches()) {
- AndroidPackage pkg = mPmInternal.getPackage(matcher.group(3));
- if (pkg != null) {
+ if (matcher.group(2) == null) {
+ Log.e(TAG, "Asked to fixup an app dir without a userId: " + path);
+ return;
+ }
+ try {
+ int userId = Integer.parseInt(matcher.group(2));
+ String packageName = matcher.group(3);
+ int uid = mContext.getPackageManager().getPackageUidAsUser(packageName, userId);
try {
- mVold.fixupAppDir(path + "/", pkg.getUid());
+ mVold.fixupAppDir(path + "/", uid);
} catch (RemoteException | ServiceSpecificException e) {
- Log.e(TAG, "Failed to fixup app dir for " + pkg.getPackageName(), e);
+ Log.e(TAG, "Failed to fixup app dir for " + packageName, e);
}
- } else {
- Log.e(TAG, "Can't find package belonging to " + path);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Invalid userId in path: " + path, e);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Couldn't find package to fixup app dir " + path, e);
}
} else {
Log.e(TAG, "Path " + path + " is not a valid application-specific directory");
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index c5c3caf..a7bf982 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -4918,52 +4918,6 @@
if (isDeviceOwner) {
return true;
}
-
- r.mInfoDenyWhileInUsePermissionInFgs =
- "Background FGS start while-in-use permission restriction [callingPackage: "
- + callingPackage
- + "; callingUid: " + callingUid
- + "; intent: " + intent
- + "]";
return false;
}
-
- // TODO: remove this toast after feature development is done
- void showWhileInUseDebugToastLocked(int uid, int op, int mode) {
- final UidRecord uidRec = mAm.mProcessList.getUidRecordLocked(uid);
- if (uidRec == null) {
- return;
- }
-
- for (int i = uidRec.procRecords.size() - 1; i >= 0; i--) {
- ProcessRecord pr = uidRec.procRecords.valueAt(i);
- if (pr.uid != uid) {
- continue;
- }
- for (int j = pr.numberOfRunningServices() - 1; j >= 0; j--) {
- ServiceRecord r = pr.getRunningServiceAt(j);
- if (!r.isForeground) {
- continue;
- }
- if (mode == DEBUG_FGS_ALLOW_WHILE_IN_USE) {
- if (!r.mAllowWhileInUsePermissionInFgs
- && r.mInfoDenyWhileInUsePermissionInFgs != null) {
- final String msg = r.mInfoDenyWhileInUsePermissionInFgs
- + " affected while-in-use permission:"
- + AppOpsManager.opToPublicName(op);
- Slog.wtf(TAG, msg);
- }
- } else if (mode == DEBUG_FGS_ENFORCE_TYPE) {
- final String msg =
- "FGS Missing foregroundServiceType in manifest file [callingPackage: "
- + r.mRecentCallingPackage
- + "; intent:" + r.intent.getIntent()
- + "] affected while-in-use permission:"
- + AppOpsManager.opToPublicName(op)
- + "; targetSdkVersion:" + r.appInfo.targetSdkVersion;
- Slog.wtf(TAG, msg);
- }
- }
- }
- }
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index caaa837..026f147 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -28,6 +28,7 @@
import static android.app.ActivityManager.INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL;
import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
+import static android.app.ActivityManager.PROCESS_STATE_TOP;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.app.ActivityManagerInternal.ALLOW_NON_FULL;
import static android.app.AppOpsManager.OP_NONE;
@@ -299,7 +300,6 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
-import android.util.SparseLongArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.util.proto.ProtoUtils;
@@ -421,7 +421,6 @@
* Priority we boost main thread and RT of top app to.
*/
public static final int TOP_APP_PRIORITY_BOOST = -10;
-
private static final String SYSTEM_PROPERTY_DEVICE_PROVISIONED =
"persist.sys.device_provisioned";
@@ -823,45 +822,7 @@
}
}
- /**
- * While starting activity, WindowManager posts a runnable to DisplayThread to updateOomAdj.
- * The latency of the thread switch could cause client app failure when the app is checking
- * {@link #isUidActive} before updateOomAdj is done.
- *
- * Use PendingStartActivityUids to save uid after WindowManager start activity and before
- * updateOomAdj is done.
- *
- * <p>NOTE: This object is protected by its own lock, NOT the global activity manager lock!
- */
- final PendingStartActivityUids mPendingStartActivityUidsLocked = new PendingStartActivityUids();
- final class PendingStartActivityUids {
- // Key is uid, value is SystemClock.elapsedRealtime() when the key is added.
- private final SparseLongArray mPendingUids = new SparseLongArray();
-
- void add(int uid) {
- if (mPendingUids.indexOfKey(uid) < 0) {
- mPendingUids.put(uid, SystemClock.elapsedRealtime());
- }
- }
-
- void delete(int uid) {
- if (mPendingUids.indexOfKey(uid) >= 0) {
- long delay = SystemClock.elapsedRealtime() - mPendingUids.get(uid);
- if (delay >= 1000) {
- Slog.wtf(TAG,
- "PendingStartActivityUids startActivity to updateOomAdj delay:"
- + delay + "ms,"
- + " uid:" + uid
- + " packageName:" + Settings.getPackageNameForUid(mContext, uid));
- }
- mPendingUids.delete(uid);
- }
- }
-
- boolean isPendingTopUid(int uid) {
- return mPendingUids.indexOfKey(uid) >= 0;
- }
- }
+ private final PendingStartActivityUids mPendingStartActivityUids;
/**
* Puts the process record in the map.
@@ -2585,6 +2546,7 @@
mFactoryTest = FACTORY_TEST_OFF;
mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
mInternal = new LocalService();
+ mPendingStartActivityUids = new PendingStartActivityUids(mContext);
}
// Note: This method is invoked on the main thread but may need to attach various
@@ -2742,6 +2704,7 @@
}
mInternal = new LocalService();
+ mPendingStartActivityUids = new PendingStartActivityUids(mContext);
}
public void setSystemServiceManager(SystemServiceManager mgr) {
@@ -6093,9 +6056,18 @@
synchronized (mPidsSelfLocked) {
for (int i = 0; i < pids.length; i++) {
ProcessRecord pr = mPidsSelfLocked.get(pids[i]);
- states[i] = (pr == null) ? PROCESS_STATE_NONEXISTENT : pr.getCurProcState();
- if (scores != null) {
- scores[i] = (pr == null) ? ProcessList.INVALID_ADJ : pr.curAdj;
+ if (pr != null) {
+ final boolean isPendingTop =
+ mPendingStartActivityUids.isPendingTopPid(pr.uid, pids[i]);
+ states[i] = isPendingTop ? PROCESS_STATE_TOP : pr.getCurProcState();
+ if (scores != null) {
+ scores[i] = isPendingTop ? ProcessList.FOREGROUND_APP_ADJ : pr.curAdj;
+ }
+ } else {
+ states[i] = PROCESS_STATE_NONEXISTENT;
+ if (scores != null) {
+ scores[i] = ProcessList.INVALID_ADJ;
+ }
}
}
}
@@ -8839,15 +8811,7 @@
return true;
}
}
-
- if (mInternal.isPendingTopUid(uid)) {
- Slog.wtf(TAG, "PendingStartActivityUids isUidActive false but"
- + " isPendingTopUid true, uid:" + uid
- + " callingPackage:" + callingPackage);
- return true;
- } else {
- return false;
- }
+ return mInternal.isPendingTopUid(uid);
}
boolean isUidActiveLocked(int uid) {
@@ -19707,15 +19671,6 @@
return false;
}
- // TODO: remove this toast after feature development is done
- @Override
- public void showWhileInUseDebugToast(int uid, int op, int mode) {
- synchronized (ActivityManagerService.this) {
- ActivityManagerService.this.mServices.showWhileInUseDebugToastLocked(
- uid, op, mode);
- }
- }
-
@Override
public void setDeviceOwnerUid(int uid) {
synchronized (ActivityManagerService.this) {
@@ -19731,22 +19686,18 @@
}
@Override
- public void updatePendingTopUid(int uid, boolean pending) {
- synchronized (mPendingStartActivityUidsLocked) {
- if (pending) {
- mPendingStartActivityUidsLocked.add(uid);
- } else {
- mPendingStartActivityUidsLocked.delete(uid);
- }
- }
+ public void addPendingTopUid(int uid, int pid) {
+ mPendingStartActivityUids.add(uid, pid);
+ }
+ @Override
+ public void deletePendingTopUid(int uid) {
+ mPendingStartActivityUids.delete(uid);
}
@Override
public boolean isPendingTopUid(int uid) {
- synchronized (mPendingStartActivityUidsLocked) {
- return mPendingStartActivityUidsLocked.isPendingTopUid(uid);
- }
+ return mPendingStartActivityUids.isPendingTopUid(uid);
}
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 14c5b2c..da5f489 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -951,7 +951,7 @@
mService.mServices.foregroundServiceProcStateChangedLocked(uidRec);
}
}
- mService.mInternal.updatePendingTopUid(uidRec.uid, false);
+ mService.mInternal.deletePendingTopUid(uidRec.uid);
}
if (mLocalPowerManager != null) {
mLocalPowerManager.finishUidChanges();
@@ -1508,16 +1508,7 @@
capabilityFromFGS |=
(fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
!= 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
- } else {
- //The FGS has the location capability, but due to FGS BG start restriction it
- //lost the capability, use temp location capability to mark this case.
- //TODO: remove this block when development is done.
- capabilityFromFGS |=
- (fgsType & FOREGROUND_SERVICE_TYPE_LOCATION) != 0
- ? ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION
- : 0;
- }
- if (s.mAllowWhileInUsePermissionInFgs) {
+
boolean enabled = false;
try {
enabled = mPlatformCompat.isChangeEnabled(
@@ -1527,23 +1518,13 @@
if (enabled) {
capabilityFromFGS |=
(fgsType & FOREGROUND_SERVICE_TYPE_CAMERA)
- != 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA
- : ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA;
+ != 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA : 0;
capabilityFromFGS |=
(fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE)
- != 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
- : ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+ != 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE : 0;
} else {
- // Remove fgsType check and assign PROCESS_CAPABILITY_FOREGROUND_CAMERA
- // and MICROPHONE when finish debugging.
- capabilityFromFGS |=
- (fgsType & FOREGROUND_SERVICE_TYPE_CAMERA)
- != 0 ? PROCESS_CAPABILITY_FOREGROUND_CAMERA
- : ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q;
- capabilityFromFGS |=
- (fgsType & FOREGROUND_SERVICE_TYPE_MICROPHONE)
- != 0 ? PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
- : ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q;
+ capabilityFromFGS |= PROCESS_CAPABILITY_FOREGROUND_CAMERA
+ | PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
}
}
}
diff --git a/services/core/java/com/android/server/am/PendingStartActivityUids.java b/services/core/java/com/android/server/am/PendingStartActivityUids.java
new file mode 100644
index 0000000..6bf9d4e
--- /dev/null
+++ b/services/core/java/com/android/server/am/PendingStartActivityUids.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2020 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.server.am;
+
+import android.content.Context;
+import android.os.SystemClock;
+import android.util.Pair;
+import android.util.Slog;
+import android.util.SparseArray;
+
+/**
+ * While starting activity, WindowManager posts a runnable to DisplayThread to updateOomAdj.
+ * The latency of the thread switch could cause client app failure when the app is checking
+ * {@link ActivityManagerService#isUidActive} before updateOomAdj is done.
+ *
+ * Use PendingStartActivityUids to save uid after WindowManager start activity and before
+ * updateOomAdj is done.
+ *
+ * <p>NOTE: This object is protected by its own lock, NOT the global activity manager lock!
+ */
+final class PendingStartActivityUids {
+ static final String TAG = ActivityManagerService.TAG;
+
+ // Key is uid, value is Pair of pid and SystemClock.elapsedRealtime() when the
+ // uid is added.
+ private final SparseArray<Pair<Integer, Long>> mPendingUids = new SparseArray();
+ private Context mContext;
+
+ PendingStartActivityUids(Context context) {
+ mContext = context;
+ }
+
+ synchronized void add(int uid, int pid) {
+ if (mPendingUids.get(uid) == null) {
+ mPendingUids.put(uid, new Pair<>(pid, SystemClock.elapsedRealtime()));
+ }
+ }
+
+ synchronized void delete(int uid) {
+ final Pair<Integer, Long> pendingPid = mPendingUids.get(uid);
+ if (pendingPid != null) {
+ final long delay = SystemClock.elapsedRealtime() - pendingPid.second;
+ if (delay >= 1000 /*ms*/) {
+ Slog.i(TAG,
+ "PendingStartActivityUids startActivity to updateOomAdj delay:"
+ + delay + "ms," + " uid:" + uid);
+ }
+ mPendingUids.delete(uid);
+ }
+ }
+
+ synchronized boolean isPendingTopPid(int uid, int pid) {
+ final Pair<Integer, Long> pendingPid = mPendingUids.get(uid);
+ if (pendingPid != null) {
+ return pendingPid.first == pid;
+ } else {
+ return false;
+ }
+ }
+
+ synchronized boolean isPendingTopUid(int uid) {
+ return mPendingUids.get(uid) != null;
+ }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 9f2a77c..2e62864 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2214,11 +2214,11 @@
app.setHasForegroundActivities(true);
}
- final Map<String, Pair<String, Long>> pkgDataInfoMap;
- final Map<String, Pair<String, Long>> whitelistedAppDataInfoMap;
+ Map<String, Pair<String, Long>> pkgDataInfoMap;
+ Map<String, Pair<String, Long>> whitelistedAppDataInfoMap;
boolean bindMountAppStorageDirs = false;
boolean bindMountAppsData = mAppDataIsolationEnabled
- && UserHandle.isApp(app.uid)
+ && (UserHandle.isApp(app.uid) || UserHandle.isIsolated(app.uid))
&& mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info);
// Get all packages belongs to the same shared uid. sharedPackages is empty array
@@ -2266,6 +2266,13 @@
}
}
+ // If it's an isolated process, it should not even mount its own app data directories,
+ // since it has no access to them anyway.
+ if (app.isolated) {
+ pkgDataInfoMap = null;
+ whitelistedAppDataInfoMap = null;
+ }
+
final Process.ProcessStartResult startResult;
if (hostingRecord.usesWebviewZygote()) {
startResult = startWebView(entryPoint,
@@ -2276,13 +2283,14 @@
} else if (hostingRecord.usesAppZygote()) {
final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
+ // We can't isolate app data and storage data as parent zygote already did that.
startResult = appZygote.getProcess().start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null, app.info.packageName,
/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
- bindMountAppsData, bindMountAppStorageDirs,
+ false, false,
new String[]{PROC_START_SEQ_IDENT + app.startSeq});
} else {
startResult = Process.start(entryPoint,
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 4670d58..9c96e6e 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -138,10 +138,7 @@
// allow while-in-use permissions in foreground service or not.
// while-in-use permissions in FGS started from background might be restricted.
boolean mAllowWhileInUsePermissionInFgs;
- // information string what/why service is denied while-in-use permissions when
- // foreground service is started from background.
- // TODO: remove this field after feature development is done
- String mInfoDenyWhileInUsePermissionInFgs;
+
// the most recent package that start/bind this service.
String mRecentCallingPackage;
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 9f27146..73c98da 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -16,11 +16,6 @@
package com.android.server.appop;
-import static android.app.ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA;
-import static android.app.ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q;
-import static android.app.ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION;
-import static android.app.ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
-import static android.app.ActivityManager.DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
@@ -520,9 +515,6 @@
public SparseBooleanArray foregroundOps;
public boolean hasForegroundWatchers;
- public long lastTimeShowDebugToast;
- public long lastTimePendingTopUid;
-
public UidState(int uid) {
this.uid = uid;
}
@@ -545,7 +537,6 @@
return MODE_ALLOWED;
} else if (mActivityManagerInternal != null
&& mActivityManagerInternal.isPendingTopUid(uid)) {
- maybeLogPendingTopUid(op, mode);
return MODE_ALLOWED;
} else if (state <= UID_STATE_TOP) {
// process is in TOP.
@@ -559,44 +550,19 @@
case AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION:
if ((capability & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) {
return MODE_ALLOWED;
- } else if ((capability
- & DEBUG_PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0) {
- // The FGS has the location capability, but due to FGS BG start
- // restriction it lost the capability, use temp location capability
- // to mark this case.
- maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ALLOW_WHILE_IN_USE);
- return MODE_IGNORED;
} else {
return MODE_IGNORED;
}
case OP_CAMERA:
if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
return MODE_ALLOWED;
- } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q)
- != 0) {
- maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
- return MODE_ALLOWED;
- } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA)
- != 0) {
- maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
- return MODE_IGNORED;
} else {
- maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ALLOW_WHILE_IN_USE);
return MODE_IGNORED;
}
case OP_RECORD_AUDIO:
if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
return MODE_ALLOWED;
- } else if ((capability
- & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q) != 0) {
- maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
- return MODE_ALLOWED;
- } else if ((capability
- & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
- maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
- return MODE_IGNORED;
} else {
- maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ALLOW_WHILE_IN_USE);
return MODE_IGNORED;
}
default:
@@ -611,38 +577,19 @@
case OP_CAMERA:
if (mActivityManagerInternal != null
&& mActivityManagerInternal.isPendingTopUid(uid)) {
- maybeLogPendingTopUid(op, mode);
return MODE_ALLOWED;
} else if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
return MODE_ALLOWED;
- } else if ((capability
- & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA_Q) != 0) {
- maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
- return MODE_ALLOWED;
- } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
- maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
- return MODE_IGNORED;
} else {
- maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ALLOW_WHILE_IN_USE);
return MODE_IGNORED;
}
case OP_RECORD_AUDIO:
if (mActivityManagerInternal != null
&& mActivityManagerInternal.isPendingTopUid(uid)) {
- maybeLogPendingTopUid(op, mode);
return MODE_ALLOWED;
} else if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
return MODE_ALLOWED;
- } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE_Q)
- != 0) {
- maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
- return MODE_ALLOWED;
- } else if ((capability & DEBUG_PROCESS_CAPABILITY_FOREGROUND_MICROPHONE)
- != 0) {
- maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ENFORCE_TYPE);
- return MODE_IGNORED;
} else {
- maybeShowWhileInUseDebugToast(op, DEBUG_FGS_ALLOW_WHILE_IN_USE);
return MODE_IGNORED;
}
default:
@@ -696,40 +643,6 @@
}
foregroundOps = which;
}
-
- // TODO: remove this toast after feature development is done
- // For DEBUG_FGS_ALLOW_WHILE_IN_USE, if the procstate is foreground service and while-in-use
- // permission is denied, show a toast message and generate a WTF log so we know
- // how many apps are impacted by the new background started foreground service while-in-use
- // permission restriction.
- // For DEBUG_FGS_ENFORCE_TYPE, The process has a foreground service that does not have
- // camera/microphone foregroundServiceType in manifest file, and the process is asking
- // AppOps for camera/microphone ops, show a toast message and generate a WTF log.
- void maybeShowWhileInUseDebugToast(int op, int mode) {
- if (mode == DEBUG_FGS_ALLOW_WHILE_IN_USE && state != UID_STATE_FOREGROUND_SERVICE) {
- return;
- }
- final long now = System.currentTimeMillis();
- if (lastTimeShowDebugToast == 0 || now - lastTimeShowDebugToast > 600000) {
- lastTimeShowDebugToast = now;
- mHandler.sendMessage(PooledLambda.obtainMessage(
- ActivityManagerInternal::showWhileInUseDebugToast,
- mActivityManagerInternal, uid, op, mode));
- }
- }
-
-
- void maybeLogPendingTopUid(int op, int mode) {
- final long now = System.currentTimeMillis();
- if (lastTimePendingTopUid == 0 || now - lastTimePendingTopUid > 300000) {
- lastTimePendingTopUid = now;
- Slog.wtf(TAG, "PendingStartActivityUids evalMode, isPendingTopUid true, uid:"
- + uid
- + " packageName:" + Settings.getPackageNameForUid(mContext, uid)
- + " op:" + op
- + " mode:" + mode);
- }
- }
}
final static class Ops extends SparseArray<Op> {
@@ -6052,7 +5965,7 @@
List<String> runtimeAppOpsList = getRuntimeAppOpsList();
AppOpsManager.HistoricalOpsRequest histOpsRequest =
new AppOpsManager.HistoricalOpsRequest.Builder(
- Instant.now().minus(7, ChronoUnit.DAYS).toEpochMilli(),
+ Math.max(Instant.now().minus(7, ChronoUnit.DAYS).toEpochMilli(), 0),
Long.MAX_VALUE).setOpNames(runtimeAppOpsList).setFlags(
OP_FLAG_SELF | OP_FLAG_TRUSTED_PROXIED).build();
appOps.getHistoricalOps(histOpsRequest, AsyncTask.THREAD_POOL_EXECUTOR,
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 5c6b481..45f95fd 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -38,6 +38,7 @@
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.text.TextUtils;
import android.util.Log;
import android.util.PrintWriterPrinter;
@@ -329,11 +330,13 @@
final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile,
suppressNoisyIntent, a2dpVolume);
+ final String name = TextUtils.emptyIfNull(device.getName());
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR
+ "postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent")
.set(MediaMetrics.Property.STATE, state == BluetoothProfile.STATE_CONNECTED
? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED)
.set(MediaMetrics.Property.INDEX, a2dpVolume)
+ .set(MediaMetrics.Property.NAME, name)
.record();
// operations of removing and posting messages related to A2DP device state change must be
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 27d9ba0..6d45aba 100755
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1893,7 +1893,7 @@
Binder.getCallingUid(), true, keyEventMode);
break;
case KeyEvent.KEYCODE_VOLUME_MUTE:
- if (event.getRepeatCount() == 0) {
+ if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
adjustSuggestedStreamVolume(AudioManager.ADJUST_TOGGLE_MUTE,
AudioManager.USE_DEFAULT_STREAM_TYPE, flags, callingPackage, caller,
Binder.getCallingUid(), true, VOL_ADJUST_NORMAL);
@@ -2155,7 +2155,8 @@
}
int oldIndex = mStreamStates[streamType].getIndex(device);
- if (adjustVolume && (direction != AudioManager.ADJUST_SAME)) {
+ if (adjustVolume
+ && (direction != AudioManager.ADJUST_SAME) && (keyEventMode != VOL_ADJUST_END)) {
mAudioHandler.removeMessages(MSG_UNMUTE_STREAM);
if (isMuteAdjust) {
@@ -2238,6 +2239,11 @@
if (streamTypeAlias == AudioSystem.STREAM_MUSIC) {
setSystemAudioVolume(oldIndex, newIndex, getStreamMaxVolume(streamType), flags);
}
+ }
+
+ final int newIndex = mStreamStates[streamType].getIndex(device);
+
+ if (adjustVolume) {
synchronized (mHdmiClientLock) {
if (mHdmiManager != null) {
// mHdmiCecSink true => mHdmiPlaybackClient != null
@@ -2290,8 +2296,7 @@
}
}
}
- int index = mStreamStates[streamType].getIndex(device);
- sendVolumeUpdate(streamType, oldIndex, index, flags, device);
+ sendVolumeUpdate(streamType, oldIndex, newIndex, flags, device);
}
// Called after a delay when volume down is pressed while muted
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 787f7f3..6f12155 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -28,6 +28,7 @@
import android.util.Slog;
import android.util.Spline;
+import com.android.internal.BrightnessSynchronizer;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
import com.android.server.display.utils.Plog;
@@ -348,9 +349,9 @@
// Normalize entire brightness range to 0 - 1.
protected static float normalizeAbsoluteBrightness(int brightness) {
- brightness = MathUtils.constrain(brightness,
- PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
- return (float) brightness / PowerManager.BRIGHTNESS_ON;
+ return BrightnessSynchronizer.brightnessIntToFloat(brightness,
+ PowerManager.BRIGHTNESS_OFF + 1, PowerManager.BRIGHTNESS_ON,
+ PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX);
}
private Pair<float[], float[]> insertControlPoint(
diff --git a/services/core/java/com/android/server/hdmi/Constants.java b/services/core/java/com/android/server/hdmi/Constants.java
index 694f0d6..13b6c7c 100644
--- a/services/core/java/com/android/server/hdmi/Constants.java
+++ b/services/core/java/com/android/server/hdmi/Constants.java
@@ -500,6 +500,22 @@
static final String PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_WAKE_UP_AND_SEND_ACTIVE_SOURCE =
"wake_up_and_send_active_source";
+ /**
+ * Property to decide the device behaviour when <Active Source> is lost.
+ *
+ * <p>This property applies to playback devices.
+ * <p>Possible values are:
+ * <ul>
+ * <li><b>none</b> No power state change (default).
+ * <li><b>standby_now</b> PowerManager.goToSleep() is called.
+ * </ul>
+ */
+ static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST =
+ "ro.hdmi.cec.source.power_state_change_on_active_source_lost";
+
+ static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE = "none";
+ static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW = "standby_now";
+
static final int RECORDING_TYPE_DIGITAL_RF = 1;
static final int RECORDING_TYPE_ANALOGUE_RF = 2;
static final int RECORDING_TYPE_EXTERNAL_PHYSICAL_ADDRESS = 3;
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index d5168ac..ef27810 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -67,6 +67,10 @@
@VisibleForTesting
protected String mPlaybackDeviceActionOnRoutingControl;
+ // Behaviour of the device when <Active Source> is lost in favor of another device.
+ @VisibleForTesting
+ protected String mPowerStateChangeOnActiveSourceLost;
+
HdmiCecLocalDevicePlayback(HdmiControlService service) {
super(service, HdmiDeviceInfo.DEVICE_PLAYBACK);
@@ -79,6 +83,10 @@
mPlaybackDeviceActionOnRoutingControl = SystemProperties.get(
Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL,
Constants.PLAYBACK_DEVICE_ACTION_ON_ROUTING_CONTROL_NONE);
+
+ mPowerStateChangeOnActiveSourceLost = SystemProperties.get(
+ Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST,
+ Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE);
}
@Override
@@ -240,6 +248,28 @@
return !getWakeLock().isHeld();
}
+ @Override
+ @ServiceThreadOnly
+ protected boolean handleActiveSource(HdmiCecMessage message) {
+ super.handleActiveSource(message);
+ if (mIsActiveSource) {
+ return true;
+ }
+ switch (mPowerStateChangeOnActiveSourceLost) {
+ case Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW:
+ mService.standby();
+ return true;
+ case Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE:
+ return true;
+ default:
+ Slog.w(TAG, "Invalid property '"
+ + Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST
+ + "' value: "
+ + mPowerStateChangeOnActiveSourceLost);
+ return true;
+ }
+ }
+
@ServiceThreadOnly
protected boolean handleUserControlPressed(HdmiCecMessage message) {
assertRunOnServiceThread();
diff --git a/services/core/java/com/android/server/locksettings/ManagedProfilePasswordCache.java b/services/core/java/com/android/server/locksettings/ManagedProfilePasswordCache.java
index d38ee67..7950fcf 100644
--- a/services/core/java/com/android/server/locksettings/ManagedProfilePasswordCache.java
+++ b/services/core/java/com/android/server/locksettings/ManagedProfilePasswordCache.java
@@ -104,8 +104,6 @@
// Generate auth-bound key to user 0 (since we the caller is user 0)
.setUserAuthenticationRequired(true)
.setUserAuthenticationValidityDurationSeconds(CACHE_TIMEOUT_SECONDS)
- // Only accessible after user 0's keyguard is unlocked
- .setUnlockedDeviceRequired(true)
.build());
key = generator.generateKey();
} catch (GeneralSecurityException e) {
@@ -171,10 +169,14 @@
public void removePassword(int userId) {
synchronized (mEncryptedPasswords) {
String keyName = getEncryptionKeyName(userId);
+ String legacyKeyName = getLegacyEncryptionKeyName(userId);
try {
if (mKeyStore.containsAlias(keyName)) {
mKeyStore.deleteEntry(keyName);
}
+ if (mKeyStore.containsAlias(legacyKeyName)) {
+ mKeyStore.deleteEntry(legacyKeyName);
+ }
} catch (KeyStoreException e) {
Slog.d(TAG, "Cannot delete key", e);
}
@@ -186,6 +188,14 @@
}
private static String getEncryptionKeyName(int userId) {
+ return "com.android.server.locksettings.unified_profile_cache_v2_" + userId;
+ }
+
+ /**
+ * Returns the legacy keystore key name when setUnlockedDeviceRequired() was set explicitly.
+ * Only existed during Android 11 internal testing period.
+ */
+ private static String getLegacyEncryptionKeyName(int userId) {
return "com.android.server.locksettings.unified_profile_cache_" + userId;
}
}
diff --git a/services/core/java/com/android/server/media/MediaKeyDispatcher.java b/services/core/java/com/android/server/media/MediaKeyDispatcher.java
index 3a29622..176ec3f 100644
--- a/services/core/java/com/android/server/media/MediaKeyDispatcher.java
+++ b/services/core/java/com/android/server/media/MediaKeyDispatcher.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.PendingIntent;
import android.media.session.ISessionManager;
import android.media.session.MediaSession;
import android.os.Binder;
@@ -76,6 +77,9 @@
/**
* Implement this to customize the logic for which MediaSession should consume which key event.
*
+ * Note: This session will have greater priority over the {@link PendingIntent} returned from
+ * {@link #getMediaButtonReceiver(KeyEvent, int, boolean)}.
+ *
* @param keyEvent a non-null KeyEvent whose key code is one of the supported media buttons.
* @param uid the uid value retrieved by calling {@link Binder#getCallingUid()} from
* {@link ISessionManager#dispatchMediaKeyEvent(String, boolean, KeyEvent, boolean)}
@@ -84,7 +88,27 @@
* @return a {@link MediaSession.Token} instance that should consume the given key event.
*/
@Nullable
- MediaSession.Token getSessionForKeyEvent(@NonNull KeyEvent keyEvent, int uid,
+ MediaSession.Token getMediaSession(@NonNull KeyEvent keyEvent, int uid,
+ boolean asSystemService) {
+ return null;
+ }
+
+ /**
+ * Implement this to customize the logic for which MediaButtonReceiver should consume a
+ * dispatched key event.
+ *
+ * Note: This pending intent will have lower priority over the {@link MediaSession.Token}
+ * returned from {@link #getMediaSession(KeyEvent, int, boolean)}.
+ *
+ * @param keyEvent a non-null KeyEvent whose key code is one of the supported media buttons.
+ * @param uid the uid value retrieved by calling {@link Binder#getCallingUid()} from
+ * {@link ISessionManager#dispatchMediaKeyEvent(String, boolean, KeyEvent, boolean)}
+ * @param asSystemService {@code true} if the event came from the system service via hardware
+ * devices. {@code false} if the event came from the app process through key injection.
+ * @return a {@link PendingIntent} instance that should receive the dispatched key event.
+ */
+ @Nullable
+ PendingIntent getMediaButtonReceiver(@NonNull KeyEvent keyEvent, int uid,
boolean asSystemService) {
return null;
}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 0e99715..c12f89c 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -1583,7 +1583,7 @@
private void onSessionInfoChangedOnHandler(@NonNull MediaRoute2Provider provider,
@NonNull RoutingSessionInfo sessionInfo) {
List<IMediaRouter2Manager> managers = getManagers();
- notifySessionInfoChangedToManagers(managers, sessionInfo);
+ notifySessionUpdatedToManagers(managers, sessionInfo);
// For system provider, notify all routers.
if (provider == mSystemProvider) {
@@ -1608,7 +1608,7 @@
private void onSessionReleasedOnHandler(@NonNull MediaRoute2Provider provider,
@NonNull RoutingSessionInfo sessionInfo) {
List<IMediaRouter2Manager> managers = getManagers();
- notifySessionInfoChangedToManagers(managers, sessionInfo);
+ notifySessionReleasedToManagers(managers, sessionInfo);
RouterRecord routerRecord = mSessionToRouterMap.get(sessionInfo.getId());
if (routerRecord == null) {
@@ -1913,15 +1913,28 @@
}
}
- private void notifySessionInfoChangedToManagers(
+ private void notifySessionUpdatedToManagers(
@NonNull List<IMediaRouter2Manager> managers,
@NonNull RoutingSessionInfo sessionInfo) {
for (IMediaRouter2Manager manager : managers) {
try {
manager.notifySessionUpdated(sessionInfo);
} catch (RemoteException ex) {
- Slog.w(TAG, "notifySessionInfosChangedToManagers: "
- + "failed to notify. Manager probably died.", ex);
+ Slog.w(TAG, "notifySessionUpdatedToManagers: "
+ + "Failed to notify. Manager probably died.", ex);
+ }
+ }
+ }
+
+ private void notifySessionReleasedToManagers(
+ @NonNull List<IMediaRouter2Manager> managers,
+ @NonNull RoutingSessionInfo sessionInfo) {
+ for (IMediaRouter2Manager manager : managers) {
+ try {
+ manager.notifySessionReleased(sessionInfo);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "notifySessionReleasedToManagers: "
+ + "Failed to notify. Manager probably died.", ex);
}
}
}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index f360a4a..afae20d 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -2404,18 +2404,32 @@
return;
}
MediaSessionRecord session = null;
+ MediaButtonReceiverHolder mediaButtonReceiverHolder = null;
- // Retrieve custom session for key event if it exists.
if (mCustomMediaKeyDispatcher != null) {
- MediaSession.Token token = mCustomMediaKeyDispatcher.getSessionForKeyEvent(
- keyEvent, uid, asSystemService);
+ MediaSession.Token token = mCustomMediaKeyDispatcher.getMediaSession(keyEvent, uid,
+ asSystemService);
if (token != null) {
session = getMediaSessionRecordLocked(token);
}
+
+ if (session == null) {
+ PendingIntent pi = mCustomMediaKeyDispatcher.getMediaButtonReceiver(keyEvent,
+ uid, asSystemService);
+ if (pi != null) {
+ mediaButtonReceiverHolder = MediaButtonReceiverHolder.create(mContext,
+ mCurrentFullUserRecord.mFullUserId, pi);
+ }
+ }
}
- if (session == null) {
+ if (session == null && mediaButtonReceiverHolder == null) {
session = (MediaSessionRecord) mCurrentFullUserRecord.getMediaButtonSessionLocked();
+
+ if (session == null) {
+ mediaButtonReceiverHolder =
+ mCurrentFullUserRecord.mLastMediaButtonReceiverHolder;
+ }
}
if (session != null) {
@@ -2438,16 +2452,12 @@
} catch (RemoteException e) {
Log.w(TAG, "Failed to send callback", e);
}
- } else if (mCurrentFullUserRecord.mLastMediaButtonReceiverHolder != null) {
+ } else if (mediaButtonReceiverHolder != null) {
if (needWakeLock) {
mKeyEventReceiver.acquireWakeLockLocked();
}
String callingPackageName =
(asSystemService) ? mContext.getPackageName() : packageName;
-
- MediaButtonReceiverHolder mediaButtonReceiverHolder =
- mCurrentFullUserRecord.mLastMediaButtonReceiverHolder;
-
boolean sent = mediaButtonReceiverHolder.send(
mContext, keyEvent, callingPackageName,
needWakeLock ? mKeyEventReceiver.mLastTimeoutId : -1, mKeyEventReceiver,
diff --git a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
index e846daf..0ec4b39 100644
--- a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
+++ b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java
@@ -108,7 +108,7 @@
public void init() {
synchronized (mLock) {
try {
- if (!mHistoryDir.mkdir()) {
+ if (!mHistoryDir.exists() && !mHistoryDir.mkdir()) {
throw new IllegalStateException("could not create history directory");
}
mVersionFile.createNewFile();
@@ -197,7 +197,7 @@
readLocked(
file, notifications, new NotificationHistoryFilter.Builder().build());
} catch (Exception e) {
- Slog.e(TAG, "error reading " + file.getBaseFile().getName(), e);
+ Slog.e(TAG, "error reading " + file.getBaseFile().getAbsolutePath(), e);
}
}
@@ -223,7 +223,7 @@
break;
}
} catch (Exception e) {
- Slog.e(TAG, "error reading " + file.getBaseFile().getName(), e);
+ Slog.e(TAG, "error reading " + file.getBaseFile().getAbsolutePath(), e);
}
}
@@ -279,7 +279,7 @@
}
file.delete();
// TODO: delete all relevant bitmaps, once they exist
- mHistoryFiles.removeLast();
+ mHistoryFiles.remove(file);
}
private void scheduleDeletion(File file, long creationTime, int retentionDays) {
@@ -317,11 +317,17 @@
private static void readLocked(AtomicFile file, NotificationHistory notificationsOut,
NotificationHistoryFilter filter) throws IOException {
- try (FileInputStream in = file.openRead()) {
+ FileInputStream in = null;
+ try {
+ in = file.openRead();
NotificationHistoryProtoHelper.read(in, notificationsOut, filter);
} catch (FileNotFoundException e) {
- Slog.e(TAG, "Cannot file " + file.getBaseFile().getName(), e);
+ Slog.e(TAG, "Cannot open " + file.getBaseFile().getAbsolutePath(), e);
throw e;
+ } finally {
+ if (in != null) {
+ in.close();
+ }
}
}
@@ -334,9 +340,15 @@
}
if (ACTION_HISTORY_DELETION.equals(action)) {
try {
- final String filePath = intent.getStringExtra(EXTRA_KEY);
- AtomicFile fileToDelete = new AtomicFile(new File(filePath));
- fileToDelete.delete();
+ synchronized (mLock) {
+ final String filePath = intent.getStringExtra(EXTRA_KEY);
+ AtomicFile fileToDelete = new AtomicFile(new File(filePath));
+ if (DEBUG) {
+ Slog.d(TAG, "Removed " + fileToDelete.getBaseFile().getName());
+ }
+ fileToDelete.delete();
+ mHistoryFiles.remove(fileToDelete);
+ }
} catch (Exception e) {
Slog.e(TAG, "Failed to delete notification history file", e);
}
@@ -345,27 +357,23 @@
};
final class WriteBufferRunnable implements Runnable {
- long currentTime = 0;
- AtomicFile latestNotificationsFile;
@Override
public void run() {
- if (DEBUG) Slog.d(TAG, "WriteBufferRunnable");
+ long time = System.currentTimeMillis();
+ run(time, new AtomicFile(new File(mHistoryDir, String.valueOf(time))));
+ }
+
+ void run(long time, AtomicFile file) {
synchronized (mLock) {
- if (currentTime == 0) {
- currentTime = System.currentTimeMillis();
- }
- if (latestNotificationsFile == null) {
- latestNotificationsFile = new AtomicFile(
- new File(mHistoryDir, String.valueOf(currentTime)));
- }
+ if (DEBUG) Slog.d(TAG, "WriteBufferRunnable "
+ + file.getBaseFile().getAbsolutePath());
try {
- writeLocked(latestNotificationsFile, mBuffer);
- mHistoryFiles.addFirst(latestNotificationsFile);
+ writeLocked(file, mBuffer);
+ mHistoryFiles.addFirst(file);
mBuffer = new NotificationHistory();
- scheduleDeletion(latestNotificationsFile.getBaseFile(), currentTime,
- HISTORY_RETENTION_DAYS);
+ scheduleDeletion(file.getBaseFile(), time, HISTORY_RETENTION_DAYS);
} catch (IOException e) {
Slog.e(TAG, "Failed to write buffer to disk. not flushing buffer", e);
}
@@ -382,7 +390,7 @@
@Override
public void run() {
- if (DEBUG) Slog.d(TAG, "RemovePackageRunnable");
+ if (DEBUG) Slog.d(TAG, "RemovePackageRunnable " + mPkg);
synchronized (mLock) {
// Remove packageName entries from pending history
mBuffer.removeNotificationsFromWrite(mPkg);
@@ -398,7 +406,7 @@
writeLocked(af, notifications);
} catch (Exception e) {
Slog.e(TAG, "Cannot clean up file on pkg removal "
- + af.getBaseFile().getName(), e);
+ + af.getBaseFile().getAbsolutePath(), e);
}
}
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index a95dc30..a9139ad 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -92,6 +92,7 @@
import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
+import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES;
@@ -1906,7 +1907,8 @@
mMetricsLogger = new MetricsLogger();
mRankingHandler = rankingHandler;
mConditionProviders = conditionProviders;
- mZenModeHelper = new ZenModeHelper(getContext(), mHandler.getLooper(), mConditionProviders);
+ mZenModeHelper = new ZenModeHelper(getContext(), mHandler.getLooper(), mConditionProviders,
+ new SysUiStatsEvent.BuilderFactory());
mZenModeHelper.addCallback(new ZenModeHelper.Callback() {
@Override
public void onConfigChanged() {
@@ -2189,6 +2191,12 @@
ConcurrentUtils.DIRECT_EXECUTOR,
mPullAtomCallback
);
+ mStatsManager.setPullAtomCallback(
+ DND_MODE_RULE,
+ null, // use default PullAtomMetadata values
+ BackgroundThread.getExecutor(),
+ mPullAtomCallback
+ );
}
private class StatsPullAtomCallbackImpl implements StatsManager.StatsPullAtomCallback {
@@ -2198,6 +2206,7 @@
case PACKAGE_NOTIFICATION_PREFERENCES:
case PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES:
case PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES:
+ case DND_MODE_RULE:
return pullNotificationStates(atomTag, data);
default:
throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
@@ -2216,6 +2225,9 @@
case PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES:
mPreferencesHelper.pullPackageChannelGroupPreferencesStats(data);
break;
+ case DND_MODE_RULE:
+ mZenModeHelper.pullRules(data);
+ break;
}
return StatsManager.PULL_SUCCESS;
}
@@ -2672,7 +2684,7 @@
mHistoryManager.addNotification(new HistoricalNotification.Builder()
.setPackage(r.getSbn().getPackageName())
.setUid(r.getSbn().getUid())
- .setUserId(r.getUserId())
+ .setUserId(r.getSbn().getNormalizedUserId())
.setChannelId(r.getChannel().getId())
.setChannelName(r.getChannel().getName().toString())
.setPostedTimeMs(System.currentTimeMillis())
@@ -4015,7 +4027,7 @@
private void cancelNotificationFromListenerLocked(ManagedServiceInfo info,
int callingUid, int callingPid, String pkg, String tag, int id, int userId) {
cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
- FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE | FLAG_BUBBLE,
+ FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE,
true,
userId, REASON_LISTENER_CANCEL, info);
}
@@ -6248,6 +6260,13 @@
mUsageStats.registerClickedByUser(r);
}
+ if (mReason == REASON_LISTENER_CANCEL
+ && (r.getNotification().flags & FLAG_BUBBLE) != 0) {
+ mNotificationDelegate.onBubbleNotificationSuppressionChanged(
+ r.getKey(), /* suppressed */ true);
+ return;
+ }
+
if ((r.getNotification().flags & mMustHaveFlags) != mMustHaveFlags) {
return;
}
diff --git a/services/core/java/com/android/server/notification/SysUiStatsEvent.java b/services/core/java/com/android/server/notification/SysUiStatsEvent.java
index 9bc2346..90737bd 100644
--- a/services/core/java/com/android/server/notification/SysUiStatsEvent.java
+++ b/services/core/java/com/android/server/notification/SysUiStatsEvent.java
@@ -58,6 +58,11 @@
mBuilder.writeBoolean(value);
return this;
}
+
+ public Builder writeByteArray(byte[] value) {
+ mBuilder.writeByteArray(value);
+ return this;
+ }
}
static class BuilderFactory {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index a490b9c..4931d3f 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -20,6 +20,10 @@
import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ENABLED;
import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_REMOVED;
import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
+import static android.service.notification.DNDModeProto.ROOT_CONFIG;
+
+import static com.android.internal.util.FrameworkStatsLog.ANNOTATION_ID_IS_UID;
+import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
import android.app.AppOpsManager;
import android.app.AutomaticZenRule;
@@ -67,6 +71,7 @@
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.StatsEvent;
import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
@@ -103,6 +108,7 @@
private final SettingsObserver mSettingsObserver;
private final AppOpsManager mAppOps;
@VisibleForTesting protected final NotificationManager mNotificationManager;
+ private final SysUiStatsEvent.BuilderFactory mStatsEventBuilderFactory;
@VisibleForTesting protected ZenModeConfig mDefaultConfig;
private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
private final ZenModeFiltering mFiltering;
@@ -130,7 +136,8 @@
private String[] mPriorityOnlyDndExemptPackages;
- public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
+ public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders,
+ SysUiStatsEvent.BuilderFactory statsEventBuilderFactory) {
mContext = context;
mHandler = new H(looper);
addCallback(mMetrics);
@@ -148,6 +155,7 @@
mFiltering = new ZenModeFiltering(mContext);
mConditions = new ZenModeConditions(this, conditionProviders);
mServiceConfig = conditionProviders.getConfig();
+ mStatsEventBuilderFactory = statsEventBuilderFactory;
}
public Looper getLooper() {
@@ -1170,6 +1178,72 @@
}
}
+ /**
+ * Generate pulled atoms about do not disturb configurations.
+ */
+ public void pullRules(List<StatsEvent> events) {
+ synchronized (mConfig) {
+ final int numConfigs = mConfigs.size();
+ int id = 0;
+ for (int i = 0; i < numConfigs; i++) {
+ final int user = mConfigs.keyAt(i);
+ final ZenModeConfig config = mConfigs.valueAt(i);
+ SysUiStatsEvent.Builder data = mStatsEventBuilderFactory.newBuilder()
+ .setAtomId(DND_MODE_RULE)
+ .writeInt(user)
+ .writeBoolean(config.manualRule != null) // enabled
+ .writeBoolean(config.areChannelsBypassingDnd)
+ .writeInt(ROOT_CONFIG)
+ .writeString("") // name, empty for root config
+ .writeInt(Process.SYSTEM_UID) // system owns root config
+ .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
+ .writeByteArray(config.toZenPolicy().toProto());
+ events.add(data.build());
+ if (config.manualRule != null && config.manualRule.enabler != null) {
+ ruleToProto(user, config.manualRule, events);
+ }
+ for (ZenRule rule : config.automaticRules.values()) {
+ ruleToProto(user, rule, events);
+ }
+ }
+ }
+ }
+
+ private void ruleToProto(int user, ZenRule rule, List<StatsEvent> events) {
+ // Make the ID safe.
+ String id = rule.id == null ? "" : rule.id;
+ if (!ZenModeConfig.DEFAULT_RULE_IDS.contains(id)) {
+ id = "";
+ }
+
+ // Look for packages and enablers, enablers get priority.
+ String pkg = rule.pkg == null ? "" : rule.pkg;
+ if (rule.enabler != null) {
+ pkg = rule.enabler;
+ id = ZenModeConfig.MANUAL_RULE_ID;
+ }
+
+ // TODO: fetch the uid from the package manager
+ int uid = "android".equals(pkg) ? Process.SYSTEM_UID : 0;
+
+ SysUiStatsEvent.Builder data;
+ data = mStatsEventBuilderFactory.newBuilder()
+ .setAtomId(DND_MODE_RULE)
+ .writeInt(user)
+ .writeBoolean(rule.enabled)
+ .writeBoolean(false) // channels_bypassing unused for rules
+ .writeInt(rule.zenMode)
+ .writeString(id)
+ .writeInt(uid)
+ .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
+ byte[] policyProto = new byte[]{};
+ if (rule.zenPolicy != null) {
+ policyProto = rule.zenPolicy.toProto();
+ }
+ data.writeByteArray(policyProto);
+ events.add(data.build());
+ }
+
@VisibleForTesting
protected final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate {
@Override
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 4b6ee71..ba60f17 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -19,6 +19,8 @@
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE;
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
+
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -109,12 +111,25 @@
private final boolean mSystemAppsQueryable;
private final FeatureConfig mFeatureConfig;
-
private final OverlayReferenceMapper mOverlayReferenceMapper;
+ private final StateProvider mStateProvider;
+
private PackageParser.SigningDetails mSystemSigningDetails;
private Set<String> mProtectedBroadcasts = new ArraySet<>();
- AppsFilter(FeatureConfig featureConfig, String[] forceQueryableWhitelist,
+ /**
+ * This structure maps uid -> uid and indicates whether access from the first should be
+ * filtered to the second. It's essentially a cache of the
+ * {@link #shouldFilterApplicationInternal(int, SettingBase, PackageSetting, int)} call.
+ * NOTE: It can only be relied upon after the system is ready to avoid unnecessary update on
+ * initial scan and is null until {@link #onSystemReady()} is called.
+ */
+ private volatile SparseArray<SparseBooleanArray> mShouldFilterCache;
+
+ @VisibleForTesting(visibility = PRIVATE)
+ AppsFilter(StateProvider stateProvider,
+ FeatureConfig featureConfig,
+ String[] forceQueryableWhitelist,
boolean systemAppsQueryable,
@Nullable OverlayReferenceMapper.Provider overlayProvider) {
mFeatureConfig = featureConfig;
@@ -122,8 +137,23 @@
mSystemAppsQueryable = systemAppsQueryable;
mOverlayReferenceMapper = new OverlayReferenceMapper(true /*deferRebuild*/,
overlayProvider);
+ mStateProvider = stateProvider;
}
+ /**
+ * Provides system state to AppsFilter via {@link CurrentStateCallback} after properly guarding
+ * the data with the package lock.
+ */
+ @VisibleForTesting(visibility = PRIVATE)
+ public interface StateProvider {
+ void runWithState(CurrentStateCallback callback);
+
+ interface CurrentStateCallback {
+ void currentState(ArrayMap<String, PackageSetting> settings, int[] users);
+ }
+ }
+
+ @VisibleForTesting(visibility = PRIVATE)
public interface FeatureConfig {
/** Called when the system is ready and components can be queried. */
@@ -140,6 +170,7 @@
/**
* Turns on logging for the given appId
+ *
* @param enable true if logging should be enabled, false if disabled.
*/
void enableLogging(int appId, boolean enable);
@@ -147,6 +178,7 @@
/**
* Initializes the package enablement state for the given package. This gives opportunity
* to do any expensive operations ahead of the actual checks.
+ *
* @param removed true if adding, false if removing
*/
void updatePackageState(PackageSetting setting, boolean removed);
@@ -162,6 +194,7 @@
@Nullable
private SparseBooleanArray mLoggingEnabled = null;
+ private AppsFilter mAppsFilter;
private FeatureConfigImpl(
PackageManagerInternal pmInternal, PackageManagerService.Injector injector) {
@@ -169,6 +202,10 @@
mInjector = injector;
}
+ public void setAppsFilter(AppsFilter filter) {
+ mAppsFilter = filter;
+ }
+
@Override
public void onSystemReady() {
mFeatureEnabled = DeviceConfig.getBoolean(
@@ -235,24 +272,25 @@
@Override
public void onCompatChange(String packageName) {
- updateEnabledState(mPmInternal.getPackage(packageName));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ updateEnabledState(mPmInternal.getPackage(packageName));
+ mAppsFilter.updateShouldFilterCacheForPackage(packageName);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
private void updateEnabledState(AndroidPackage pkg) {
- final long token = Binder.clearCallingIdentity();
- try {
- // TODO(b/135203078): Do not use toAppInfo
- final boolean enabled =
- mInjector.getCompatibility().isChangeEnabled(
- PackageManager.FILTER_APPLICATION_QUERY,
- pkg.toAppInfoWithoutState());
- if (enabled) {
- mDisabledPackages.remove(pkg.getPackageName());
- } else {
- mDisabledPackages.add(pkg.getPackageName());
- }
- } finally {
- Binder.restoreCallingIdentity(token);
+ // TODO(b/135203078): Do not use toAppInfo
+ final boolean enabled =
+ mInjector.getCompatibility().isChangeEnabled(
+ PackageManager.FILTER_APPLICATION_QUERY,
+ pkg.toAppInfoWithoutState());
+ if (enabled) {
+ mDisabledPackages.remove(pkg.getPackageName());
+ } else {
+ mDisabledPackages.add(pkg.getPackageName());
}
}
@@ -275,7 +313,7 @@
final boolean forceSystemAppsQueryable =
injector.getContext().getResources()
.getBoolean(R.bool.config_forceSystemPackagesQueryable);
- final FeatureConfig featureConfig = new FeatureConfigImpl(pms, injector);
+ final FeatureConfigImpl featureConfig = new FeatureConfigImpl(pms, injector);
final String[] forcedQueryablePackageNames;
if (forceSystemAppsQueryable) {
// all system apps already queryable, no need to read and parse individual exceptions
@@ -288,8 +326,16 @@
forcedQueryablePackageNames[i] = forcedQueryablePackageNames[i].intern();
}
}
- return new AppsFilter(featureConfig, forcedQueryablePackageNames,
- forceSystemAppsQueryable, null);
+ final StateProvider stateProvider = command -> {
+ synchronized (injector.getLock()) {
+ command.currentState(injector.getSettings().mPackages,
+ injector.getUserManagerInternal().getUserIds());
+ }
+ };
+ AppsFilter appsFilter = new AppsFilter(stateProvider, featureConfig,
+ forcedQueryablePackageNames, forceSystemAppsQueryable, null);
+ featureConfig.setAppsFilter(appsFilter);
+ return appsFilter;
}
public FeatureConfig getFeatureConfig() {
@@ -412,28 +458,54 @@
* visibility of the caller from the target.
*
* @param recipientUid the uid gaining visibility of the {@code visibleUid}.
- * @param visibleUid the uid becoming visible to the {@recipientUid}
+ * @param visibleUid the uid becoming visible to the {@recipientUid}
*/
public void grantImplicitAccess(int recipientUid, int visibleUid) {
- if (recipientUid != visibleUid
- && mImplicitlyQueryable.add(recipientUid, visibleUid) && DEBUG_LOGGING) {
- Slog.i(TAG, "implicit access granted: " + recipientUid + " -> " + visibleUid);
+ if (recipientUid != visibleUid) {
+ if (mImplicitlyQueryable.add(recipientUid, visibleUid) && DEBUG_LOGGING) {
+ Slog.i(TAG, "implicit access granted: " + recipientUid + " -> " + visibleUid);
+ }
+ if (mShouldFilterCache != null) {
+ // update the cache in a one-off manner since we've got all the information we need.
+ SparseBooleanArray visibleUids = mShouldFilterCache.get(recipientUid);
+ if (visibleUids == null) {
+ visibleUids = new SparseBooleanArray();
+ mShouldFilterCache.put(recipientUid, visibleUids);
+ }
+ visibleUids.put(visibleUid, false);
+ }
}
}
public void onSystemReady() {
+ mShouldFilterCache = new SparseArray<>();
mFeatureConfig.onSystemReady();
mOverlayReferenceMapper.rebuildIfDeferred();
+ updateEntireShouldFilterCache();
}
/**
* Adds a package that should be considered when filtering visibility between apps.
*
- * @param newPkgSetting the new setting being added
- * @param existingSettings all other settings currently on the device.
+ * @param newPkgSetting the new setting being added
*/
- public void addPackage(PackageSetting newPkgSetting,
- ArrayMap<String, PackageSetting> existingSettings) {
+ public void addPackage(PackageSetting newPkgSetting) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage");
+ try {
+ mStateProvider.runWithState((settings, users) -> {
+ addPackageInternal(newPkgSetting, settings, users);
+ if (mShouldFilterCache != null) {
+ updateShouldFilterCacheForPackage(
+ null, newPkgSetting, settings, users, settings.size());
+ } // else, rebuild entire cache when system is ready
+ });
+ } finally {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+ }
+
+ private void addPackageInternal(PackageSetting newPkgSetting,
+ ArrayMap<String, PackageSetting> existingSettings, int[] allUsers) {
if (Objects.equals("android", newPkgSetting.name)) {
// let's set aside the framework signatures
mSystemSigningDetails = newPkgSetting.signatures.mSigningDetails;
@@ -446,79 +518,151 @@
}
}
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "filter.addPackage");
- try {
- final AndroidPackage newPkg = newPkgSetting.pkg;
- if (newPkg == null) {
- // nothing to add
- return;
- }
+ final AndroidPackage newPkg = newPkgSetting.pkg;
+ if (newPkg == null) {
+ // nothing to add
+ return;
+ }
- if (!newPkg.getProtectedBroadcasts().isEmpty()) {
- mProtectedBroadcasts.addAll(newPkg.getProtectedBroadcasts());
- recomputeComponentVisibility(existingSettings, newPkg.getPackageName());
- }
+ if (!newPkg.getProtectedBroadcasts().isEmpty()) {
+ mProtectedBroadcasts.addAll(newPkg.getProtectedBroadcasts());
+ recomputeComponentVisibility(existingSettings, newPkg.getPackageName());
+ }
- final boolean newIsForceQueryable =
- mForceQueryable.contains(newPkgSetting.appId)
- /* shared user that is already force queryable */
- || newPkg.isForceQueryable()
- || newPkgSetting.forceQueryableOverride
- || (newPkgSetting.isSystem() && (mSystemAppsQueryable
- || ArrayUtils.contains(mForceQueryableByDevicePackageNames,
- newPkg.getPackageName())));
- if (newIsForceQueryable
- || (mSystemSigningDetails != null
- && isSystemSigned(mSystemSigningDetails, newPkgSetting))) {
- mForceQueryable.add(newPkgSetting.appId);
- }
+ final boolean newIsForceQueryable =
+ mForceQueryable.contains(newPkgSetting.appId)
+ /* shared user that is already force queryable */
+ || newPkg.isForceQueryable()
+ || newPkgSetting.forceQueryableOverride
+ || (newPkgSetting.isSystem() && (mSystemAppsQueryable
+ || ArrayUtils.contains(mForceQueryableByDevicePackageNames,
+ newPkg.getPackageName())));
+ if (newIsForceQueryable
+ || (mSystemSigningDetails != null
+ && isSystemSigned(mSystemSigningDetails, newPkgSetting))) {
+ mForceQueryable.add(newPkgSetting.appId);
+ }
- for (int i = existingSettings.size() - 1; i >= 0; i--) {
- final PackageSetting existingSetting = existingSettings.valueAt(i);
- if (existingSetting.appId == newPkgSetting.appId || existingSetting.pkg == null) {
- continue;
+ for (int i = existingSettings.size() - 1; i >= 0; i--) {
+ final PackageSetting existingSetting = existingSettings.valueAt(i);
+ if (existingSetting.appId == newPkgSetting.appId || existingSetting.pkg == null) {
+ continue;
+ }
+ final AndroidPackage existingPkg = existingSetting.pkg;
+ // let's evaluate the ability of already added packages to see this new package
+ if (!newIsForceQueryable) {
+ if (canQueryViaComponents(existingPkg, newPkg, mProtectedBroadcasts)) {
+ mQueriesViaComponent.add(existingSetting.appId, newPkgSetting.appId);
}
- final AndroidPackage existingPkg = existingSetting.pkg;
- // let's evaluate the ability of already added packages to see this new package
- if (!newIsForceQueryable) {
- if (canQueryViaComponents(existingPkg, newPkg, mProtectedBroadcasts)) {
- mQueriesViaComponent.add(existingSetting.appId, newPkgSetting.appId);
- }
- if (canQueryViaPackage(existingPkg, newPkg)
- || canQueryAsInstaller(existingSetting, newPkg)) {
- mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId);
- }
- }
- // now we'll evaluate our new package's ability to see existing packages
- if (!mForceQueryable.contains(existingSetting.appId)) {
- if (canQueryViaComponents(newPkg, existingPkg, mProtectedBroadcasts)) {
- mQueriesViaComponent.add(newPkgSetting.appId, existingSetting.appId);
- }
- if (canQueryViaPackage(newPkg, existingPkg)
- || canQueryAsInstaller(newPkgSetting, existingPkg)) {
- mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId);
- }
- }
- // if either package instruments the other, mark both as visible to one another
- if (pkgInstruments(newPkgSetting, existingSetting)
- || pkgInstruments(existingSetting, newPkgSetting)) {
- mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId);
+ if (canQueryViaPackage(existingPkg, newPkg)
+ || canQueryAsInstaller(existingSetting, newPkg)) {
mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId);
}
}
-
- int existingSize = existingSettings.size();
- ArrayMap<String, AndroidPackage> existingPkgs = new ArrayMap<>(existingSize);
- for (int index = 0; index < existingSize; index++) {
- PackageSetting pkgSetting = existingSettings.valueAt(index);
- if (pkgSetting.pkg != null) {
- existingPkgs.put(pkgSetting.name, pkgSetting.pkg);
+ // now we'll evaluate our new package's ability to see existing packages
+ if (!mForceQueryable.contains(existingSetting.appId)) {
+ if (canQueryViaComponents(newPkg, existingPkg, mProtectedBroadcasts)) {
+ mQueriesViaComponent.add(newPkgSetting.appId, existingSetting.appId);
+ }
+ if (canQueryViaPackage(newPkg, existingPkg)
+ || canQueryAsInstaller(newPkgSetting, existingPkg)) {
+ mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId);
}
}
- mOverlayReferenceMapper.addPkg(newPkgSetting.pkg, existingPkgs);
- mFeatureConfig.updatePackageState(newPkgSetting, false /*removed*/);
- } finally {
- Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ // if either package instruments the other, mark both as visible to one another
+ if (pkgInstruments(newPkgSetting, existingSetting)
+ || pkgInstruments(existingSetting, newPkgSetting)) {
+ mQueriesViaPackage.add(newPkgSetting.appId, existingSetting.appId);
+ mQueriesViaPackage.add(existingSetting.appId, newPkgSetting.appId);
+ }
+ }
+
+ int existingSize = existingSettings.size();
+ ArrayMap<String, AndroidPackage> existingPkgs = new ArrayMap<>(existingSize);
+ for (int index = 0; index < existingSize; index++) {
+ PackageSetting pkgSetting = existingSettings.valueAt(index);
+ if (pkgSetting.pkg != null) {
+ existingPkgs.put(pkgSetting.name, pkgSetting.pkg);
+ }
+ }
+ mOverlayReferenceMapper.addPkg(newPkgSetting.pkg, existingPkgs);
+ mFeatureConfig.updatePackageState(newPkgSetting, false /*removed*/);
+ }
+
+ private void removeAppIdFromVisibilityCache(int appId) {
+ if (mShouldFilterCache == null) {
+ return;
+ }
+ for (int i = mShouldFilterCache.size() - 1; i >= 0; i--) {
+ if (UserHandle.getAppId(mShouldFilterCache.keyAt(i)) == appId) {
+ mShouldFilterCache.removeAt(i);
+ continue;
+ }
+ SparseBooleanArray targetSparseArray = mShouldFilterCache.valueAt(i);
+ for (int j = targetSparseArray.size() - 1; j >= 0; j--) {
+ if (UserHandle.getAppId(targetSparseArray.keyAt(j)) == appId) {
+ targetSparseArray.removeAt(j);
+ }
+ }
+ }
+ }
+
+ private void updateEntireShouldFilterCache() {
+ mStateProvider.runWithState((settings, users) -> {
+ mShouldFilterCache.clear();
+ for (int i = settings.size() - 1; i >= 0; i--) {
+ updateShouldFilterCacheForPackage(
+ null /*skipPackage*/, settings.valueAt(i), settings, users, i);
+ }
+ });
+ }
+
+ public void onUsersChanged() {
+ if (mShouldFilterCache != null) {
+ updateEntireShouldFilterCache();
+ }
+ }
+
+ private void updateShouldFilterCacheForPackage(String packageName) {
+ mStateProvider.runWithState((settings, users) -> {
+ updateShouldFilterCacheForPackage(null /* skipPackage */, settings.get(packageName),
+ settings, users, settings.size() /*maxIndex*/);
+ });
+
+ }
+
+ private void updateShouldFilterCacheForPackage(@Nullable String skipPackageName,
+ PackageSetting subjectSetting, ArrayMap<String, PackageSetting> allSettings,
+ int[] allUsers, int maxIndex) {
+ for (int i = Math.min(maxIndex, allSettings.size() - 1); i >= 0; i--) {
+ PackageSetting otherSetting = allSettings.valueAt(i);
+ if (subjectSetting.appId == otherSetting.appId) {
+ continue;
+ }
+ //noinspection StringEquality
+ if (subjectSetting.name == skipPackageName || otherSetting.name == skipPackageName) {
+ continue;
+ }
+ for (int su = 0; su < allUsers.length; su++) {
+ int subjectUser = allUsers[su];
+ for (int ou = su; ou < allUsers.length; ou++) {
+ int otherUser = allUsers[ou];
+ int subjectUid = UserHandle.getUid(subjectUser, subjectSetting.appId);
+ if (!mShouldFilterCache.contains(subjectUid)) {
+ mShouldFilterCache.put(subjectUid, new SparseBooleanArray());
+ }
+ int otherUid = UserHandle.getUid(otherUser, otherSetting.appId);
+ if (!mShouldFilterCache.contains(otherUid)) {
+ mShouldFilterCache.put(otherUid, new SparseBooleanArray());
+ }
+ mShouldFilterCache.get(subjectUid).put(otherUid,
+ shouldFilterApplicationInternal(
+ subjectUid, subjectSetting, otherSetting, otherUser));
+ mShouldFilterCache.get(otherUid).put(subjectUid,
+ shouldFilterApplicationInternal(
+ otherUid, otherSetting, subjectSetting, subjectUser));
+ }
+ }
}
}
@@ -569,6 +713,7 @@
}
}
}
+
/**
* Fetches all app Ids that a given setting is currently visible to, per provided user. This
* only includes UIDs >= {@link Process#FIRST_APPLICATION_UID} as all other UIDs can already see
@@ -577,11 +722,11 @@
* If the setting is visible to all UIDs, null is returned. If an app is not visible to any
* applications, the int array will be empty.
*
- * @param users the set of users that should be evaluated for this calculation
+ * @param users the set of users that should be evaluated for this calculation
* @param existingSettings the set of all package settings that currently exist on device
* @return a SparseArray mapping userIds to a sorted int array of appIds that may view the
- * provided setting or null if the app is visible to all and no whitelist should be
- * applied.
+ * provided setting or null if the app is visible to all and no whitelist should be
+ * applied.
*/
@Nullable
public SparseArray<int[]> getVisibilityWhitelist(PackageSetting setting, int[] users,
@@ -626,52 +771,60 @@
/**
* Removes a package for consideration when filtering visibility between apps.
*
- * @param setting the setting of the package being removed.
- * @param allUsers array of all current users on device.
+ * @param setting the setting of the package being removed.
*/
- public void removePackage(PackageSetting setting, int[] allUsers,
- ArrayMap<String, PackageSetting> existingSettings) {
+ public void removePackage(PackageSetting setting) {
+ removeAppIdFromVisibilityCache(setting.appId);
+ mStateProvider.runWithState((settings, users) -> {
+ for (int u = 0; u < users.length; u++) {
+ final int userId = users[u];
+ final int removingUid = UserHandle.getUid(userId, setting.appId);
+ mImplicitlyQueryable.remove(removingUid);
+ for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) {
+ mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i), removingUid);
+ }
+ }
+
+ mQueriesViaComponent.remove(setting.appId);
+ for (int i = mQueriesViaComponent.size() - 1; i >= 0; i--) {
+ mQueriesViaComponent.remove(mQueriesViaComponent.keyAt(i), setting.appId);
+ }
+ mQueriesViaPackage.remove(setting.appId);
+ for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) {
+ mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i), setting.appId);
+ }
+
+ // re-add other shared user members to re-establish visibility between them and other
+ // packages
+ if (setting.sharedUser != null) {
+ for (int i = setting.sharedUser.packages.size() - 1; i >= 0; i--) {
+ if (setting.sharedUser.packages.valueAt(i) == setting) {
+ continue;
+ }
+ addPackageInternal(
+ setting.sharedUser.packages.valueAt(i), settings, users);
+ }
+ }
+
+ if (!setting.pkg.getProtectedBroadcasts().isEmpty()) {
+ final String removingPackageName = setting.pkg.getPackageName();
+ mProtectedBroadcasts.clear();
+ mProtectedBroadcasts.addAll(
+ collectProtectedBroadcasts(settings, removingPackageName));
+ recomputeComponentVisibility(settings, removingPackageName);
+ }
+
+ mOverlayReferenceMapper.removePkg(setting.name);
+ mFeatureConfig.updatePackageState(setting, true /*removed*/);
+
+ if (mShouldFilterCache != null) {
+ updateShouldFilterCacheForPackage(
+ setting.name, setting, settings, users, settings.size());
+ }
+ });
mForceQueryable.remove(setting.appId);
- for (int u = 0; u < allUsers.length; u++) {
- final int userId = allUsers[u];
- final int removingUid = UserHandle.getUid(userId, setting.appId);
- mImplicitlyQueryable.remove(removingUid);
- for (int i = mImplicitlyQueryable.size() - 1; i >= 0; i--) {
- mImplicitlyQueryable.remove(mImplicitlyQueryable.keyAt(i), removingUid);
- }
- }
- mQueriesViaComponent.remove(setting.appId);
- for (int i = mQueriesViaComponent.size() - 1; i >= 0; i--) {
- mQueriesViaComponent.remove(mQueriesViaComponent.keyAt(i), setting.appId);
- }
- mQueriesViaPackage.remove(setting.appId);
- for (int i = mQueriesViaPackage.size() - 1; i >= 0; i--) {
- mQueriesViaPackage.remove(mQueriesViaPackage.keyAt(i), setting.appId);
- }
-
- // re-add other shared user members to re-establish visibility between them and other
- // packages
- if (setting.sharedUser != null) {
- for (int i = setting.sharedUser.packages.size() - 1; i >= 0; i--) {
- if (setting.sharedUser.packages.valueAt(i) == setting) {
- continue;
- }
- addPackage(setting.sharedUser.packages.valueAt(i), existingSettings);
- }
- }
-
- if (!setting.pkg.getProtectedBroadcasts().isEmpty()) {
- final String removingPackageName = setting.pkg.getPackageName();
- mProtectedBroadcasts.clear();
- mProtectedBroadcasts.addAll(
- collectProtectedBroadcasts(existingSettings, removingPackageName));
- recomputeComponentVisibility(existingSettings, removingPackageName);
- }
-
- mOverlayReferenceMapper.removePkg(setting.name);
- mFeatureConfig.updatePackageState(setting, true /*removed*/);
}
/**
@@ -688,11 +841,32 @@
PackageSetting targetPkgSetting, int userId) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplication");
try {
-
- if (!shouldFilterApplicationInternal(
- callingUid, callingSetting, targetPkgSetting, userId)) {
+ if (callingUid < Process.FIRST_APPLICATION_UID
+ || UserHandle.getAppId(callingUid) == targetPkgSetting.appId) {
return false;
}
+ if (mShouldFilterCache != null) { // use cache
+ SparseBooleanArray shouldFilterTargets = mShouldFilterCache.get(callingUid);
+ final int targetUid = UserHandle.getUid(userId, targetPkgSetting.appId);
+ if (shouldFilterTargets == null) {
+ Slog.wtf(TAG, "Encountered calling uid with no cached rules: " + callingUid);
+ return true;
+ }
+ int indexOfTargetUid = shouldFilterTargets.indexOfKey(targetUid);
+ if (indexOfTargetUid < 0) {
+ Slog.w(TAG, "Encountered calling -> target with no cached rules: "
+ + callingUid + " -> " + targetUid);
+ return true;
+ }
+ if (!shouldFilterTargets.valueAt(indexOfTargetUid)) {
+ return false;
+ }
+ } else {
+ if (!shouldFilterApplicationInternal(
+ callingUid, callingSetting, targetPkgSetting, userId)) {
+ return false;
+ }
+ }
if (DEBUG_LOGGING || mFeatureConfig.isLoggingEnabled(UserHandle.getAppId(callingUid))) {
log(callingSetting, targetPkgSetting, "BLOCKED");
}
@@ -703,7 +877,7 @@
}
private boolean shouldFilterApplicationInternal(int callingUid, SettingBase callingSetting,
- PackageSetting targetPkgSetting, int userId) {
+ PackageSetting targetPkgSetting, int targetUserId) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "shouldFilterApplicationInternal");
try {
final boolean featureEnabled = mFeatureConfig.isGloballyEnabled();
@@ -713,12 +887,6 @@
}
return false;
}
- if (callingUid < Process.FIRST_APPLICATION_UID) {
- if (DEBUG_LOGGING) {
- Slog.d(TAG, "filtering skipped; " + callingUid + " is system");
- }
- return false;
- }
if (callingSetting == null) {
Slog.wtf(TAG, "No setting found for non system uid " + callingUid);
return true;
@@ -727,8 +895,14 @@
final ArraySet<PackageSetting> callingSharedPkgSettings;
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "callingSetting instanceof");
if (callingSetting instanceof PackageSetting) {
- callingPkgSetting = (PackageSetting) callingSetting;
- callingSharedPkgSettings = null;
+ if (((PackageSetting) callingSetting).sharedUser == null) {
+ callingPkgSetting = (PackageSetting) callingSetting;
+ callingSharedPkgSettings = null;
+ } else {
+ callingPkgSetting = null;
+ callingSharedPkgSettings =
+ ((PackageSetting) callingSetting).sharedUser.packages;
+ }
} else {
callingPkgSetting = null;
callingSharedPkgSettings = ((SharedUserSetting) callingSetting).packages;
@@ -786,13 +960,17 @@
}
try {
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "hasPermission");
- if (callingSetting.getPermissionsState().hasPermission(
- Manifest.permission.QUERY_ALL_PACKAGES, UserHandle.getUserId(callingUid))) {
- if (DEBUG_LOGGING) {
- log(callingSetting, targetPkgSetting, "has query-all permission");
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "requestsQueryAllPackages");
+ if (callingPkgSetting != null) {
+ if (requestsQueryAllPackages(callingPkgSetting)) {
+ return false;
}
- return false;
+ } else {
+ for (int i = callingSharedPkgSettings.size() - 1; i >= 0; i--) {
+ if (requestsQueryAllPackages(callingSharedPkgSettings.valueAt(i))) {
+ return false;
+ }
+ }
}
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -833,7 +1011,7 @@
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "mImplicitlyQueryable");
- final int targetUid = UserHandle.getUid(userId, targetAppId);
+ final int targetUid = UserHandle.getUid(targetUserId, targetAppId);
if (mImplicitlyQueryable.contains(callingUid, targetUid)) {
if (DEBUG_LOGGING) {
log(callingSetting, targetPkgSetting, "implicitly queryable for user");
@@ -871,13 +1049,20 @@
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
-
return true;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
+
+ private static boolean requestsQueryAllPackages(PackageSetting pkgSetting) {
+ // we're not guaranteed to have permissions yet analyzed at package add, so we inspect the
+ // package directly
+ return pkgSetting.pkg.getRequestedPermissions().contains(
+ Manifest.permission.QUERY_ALL_PACKAGES);
+ }
+
/** Returns {@code true} if the source package instruments the target package. */
private static boolean pkgInstruments(PackageSetting source, PackageSetting target) {
try {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 766fae6..fd37f04 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -10713,6 +10713,20 @@
return resultList;
}
+ private int getVendorPartitionVersion() {
+ final String version = SystemProperties.get("ro.vndk.version");
+ if (!version.isEmpty()) {
+ try {
+ return Integer.parseInt(version);
+ } catch (NumberFormatException ignore) {
+ if (ArrayUtils.contains(Build.VERSION.ACTIVE_CODENAMES, version)) {
+ return Build.VERSION_CODES.CUR_DEVELOPMENT;
+ }
+ }
+ }
+ return Build.VERSION_CODES.P;
+ }
+
@GuardedBy({"mInstallLock", "mLock"})
private ScanResult scanPackageTracedLI(ParsedPackage parsedPackage,
final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
@@ -10894,7 +10908,7 @@
// Scan as privileged apps that share a user with a priv-app.
final boolean skipVendorPrivilegeScan = ((scanFlags & SCAN_AS_VENDOR) != 0)
- && SystemProperties.getInt("ro.vndk.version", 28) < 28;
+ && getVendorPartitionVersion() < 28;
if (((scanFlags & SCAN_AS_PRIVILEGED) == 0)
&& !pkg.isPrivileged()
&& (pkg.getSharedUserId() != null)
@@ -12070,6 +12084,20 @@
+ pkg.getPackageName()
+ " is static and cannot be upgraded.");
}
+ } else {
+ if ((scanFlags & SCAN_AS_VENDOR) != 0) {
+ if (pkg.getTargetSdkVersion() < getVendorPartitionVersion()) {
+ Slog.w(TAG, "System overlay " + pkg.getPackageName()
+ + " targets an SDK below the required SDK level of vendor"
+ + " overlays (" + getVendorPartitionVersion() + ")."
+ + " This will become an install error in a future release");
+ }
+ } else if (pkg.getTargetSdkVersion() < Build.VERSION.SDK_INT) {
+ Slog.w(TAG, "System overlay " + pkg.getPackageName()
+ + " targets an SDK below the required SDK level of system"
+ + " overlays (" + Build.VERSION.SDK_INT + ")."
+ + " This will become an install error in a future release");
+ }
}
} else {
// A non-preloaded overlay packages must have targetSdkVersion >= Q, or be
@@ -12334,7 +12362,7 @@
ksms.addScannedPackageLPw(pkg);
mComponentResolver.addAllComponents(pkg, chatty);
- mAppsFilter.addPackage(pkgSetting, mSettings.mPackages);
+ mAppsFilter.addPackage(pkgSetting);
// Don't allow ephemeral applications to define new permissions groups.
if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
@@ -12508,8 +12536,6 @@
void cleanPackageDataStructuresLILPw(AndroidPackage pkg, boolean chatty) {
mComponentResolver.removeAllComponents(pkg, chatty);
- mAppsFilter.removePackage(getPackageSetting(pkg.getPackageName()),
- mInjector.getUserManagerInternal().getUserIds(), mSettings.mPackages);
mPermissionManager.removeAllPermissions(pkg, chatty);
final int instrumentationSize = ArrayUtils.size(pkg.getInstrumentations());
@@ -14225,7 +14251,7 @@
// Okay!
targetPackageSetting.setInstallerPackageName(installerPackageName);
mSettings.addInstallerPackageNames(targetPackageSetting.installSource);
- mAppsFilter.addPackage(targetPackageSetting, mSettings.mPackages);
+ mAppsFilter.addPackage(targetPackageSetting);
scheduleWriteSettingsLocked();
}
}
@@ -18678,6 +18704,7 @@
clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL, true);
clearDefaultBrowserIfNeeded(packageName);
mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName);
+ mAppsFilter.removePackage(getPackageSetting(packageName));
removedAppId = mSettings.removePackageLPw(packageName);
if (outInfo != null) {
outInfo.removedAppId = removedAppId;
@@ -23435,6 +23462,7 @@
scheduleWritePackageRestrictionsLocked(userId);
scheduleWritePackageListLocked(userId);
primeDomainVerificationsLPw(userId);
+ mAppsFilter.onUsersChanged();
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 40fa798..2a6997c 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -989,6 +989,15 @@
ensureCanModifyQuietMode(
callingPackage, Binder.getCallingUid(), userId, target != null, dontAskCredential);
+
+ if (onlyIfCredentialNotRequired && callingPackage.equals(
+ getPackageManagerInternal().getSystemUiServiceComponent().getPackageName())) {
+ // This is to prevent SysUI from accidentally allowing the profile to turned on
+ // without password when keyguard is still locked.
+ throw new SecurityException("SystemUI is not allowed to set "
+ + "QUIET_MODE_DISABLE_ONLY_IF_CREDENTIAL_NOT_REQUIRED");
+ }
+
final long identity = Binder.clearCallingIdentity();
try {
if (enableQuietMode) {
@@ -996,7 +1005,17 @@
userId, true /* enableQuietMode */, target, callingPackage);
return true;
}
- mLockPatternUtils.tryUnlockWithCachedUnifiedChallenge(userId);
+ if (mLockPatternUtils.isManagedProfileWithUnifiedChallenge(userId)) {
+ KeyguardManager km = mContext.getSystemService(KeyguardManager.class);
+ // Normally only attempt to auto-unlock unified challenge if keyguard is not showing
+ // (to stop turning profile on automatically via the QS tile), except when we
+ // are called with QUIET_MODE_DISABLE_ONLY_IF_CREDENTIAL_NOT_REQUIRED, in which
+ // case always attempt to auto-unlock.
+ if (!km.isDeviceLocked(mLocalService.getProfileParentId(userId))
+ || onlyIfCredentialNotRequired) {
+ mLockPatternUtils.tryUnlockWithCachedUnifiedChallenge(userId);
+ }
+ }
final boolean needToShowConfirmCredential = !dontAskCredential
&& mLockPatternUtils.isSecure(userId)
&& !StorageManager.isUserKeyUnlocked(userId);
@@ -1029,6 +1048,8 @@
*/
private void ensureCanModifyQuietMode(String callingPackage, int callingUid,
@UserIdInt int targetUserId, boolean startIntent, boolean dontAskCredential) {
+ verifyCallingPackage(callingPackage, callingUid);
+
if (hasManageUsersPermission()) {
return;
}
@@ -1050,7 +1071,6 @@
return;
}
- verifyCallingPackage(callingPackage, callingUid);
final ShortcutServiceInternal shortcutInternal =
LocalServices.getService(ShortcutServiceInternal.class);
if (shortcutInternal != null) {
diff --git a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
index 58732b4..7c89b98 100644
--- a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
+++ b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
@@ -96,6 +96,8 @@
class UserSystemPackageInstaller {
private static final String TAG = "UserManagerService";
+ private static final boolean DEBUG = false;
+
/**
* System Property whether to only install system packages on a user if they're whitelisted for
* that user type. These are flags and can be freely combined.
@@ -328,12 +330,15 @@
// Check whether all whitelisted packages are indeed on the system.
final String notPresentFmt = "%s is whitelisted but not present.";
final String notSystemFmt = "%s is whitelisted and present but not a system package.";
+ final String overlayPackageFmt = "%s is whitelisted but it's auto-generated RRO package.";
for (String pkgName : allWhitelistedPackages) {
final AndroidPackage pkg = pmInt.getPackage(pkgName);
if (pkg == null) {
warnings.add(String.format(notPresentFmt, pkgName));
} else if (!pkg.isSystem()) {
warnings.add(String.format(notSystemFmt, pkgName));
+ } else if (isAutoGeneratedRRO(pkg)) {
+ warnings.add(String.format(overlayPackageFmt, pkgName));
}
}
return warnings;
@@ -407,6 +412,23 @@
return isImplicitWhitelistSystemMode(getWhitelistMode());
}
+ /**
+ * Whether package name has auto-generated RRO package name suffix.
+ */
+ @VisibleForTesting
+ static boolean hasAutoGeneratedRROSuffix(String name) {
+ return name.endsWith(".auto_generated_rro_product__")
+ || name.endsWith(".auto_generated_rro_vendor__");
+ }
+
+ /**
+ * Whether the package is auto-generated RRO package.
+ */
+ private static boolean isAutoGeneratedRRO(AndroidPackage pkg) {
+ return pkg.isOverlay()
+ && (hasAutoGeneratedRROSuffix(pkg.getManifestPackageName()));
+ }
+
/** See {@link #isEnforceMode()}. */
private static boolean isEnforceMode(int whitelistMode) {
return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE) != 0;
@@ -518,7 +540,18 @@
static boolean shouldInstallPackage(AndroidPackage sysPkg,
@NonNull ArrayMap<String, Long> userTypeWhitelist,
@NonNull Set<String> userWhitelist, boolean implicitlyWhitelist) {
- final String pkgName = sysPkg.getManifestPackageName();
+ final String pkgName;
+ if (isAutoGeneratedRRO(sysPkg)) {
+ pkgName = sysPkg.getOverlayTarget();
+ if (DEBUG) {
+ Slog.i(TAG, "shouldInstallPackage(): " + sysPkg.getManifestPackageName()
+ + " is auto-generated RRO package, will look for overlay system package: "
+ + pkgName);
+ }
+ } else {
+ pkgName = sysPkg.getManifestPackageName();
+ }
+
return (implicitlyWhitelist && !userTypeWhitelist.containsKey(pkgName))
|| userWhitelist.contains(pkgName);
}
diff --git a/services/core/java/com/android/server/power/PreRebootLogger.java b/services/core/java/com/android/server/power/PreRebootLogger.java
index cda00b4..c9e81ed 100644
--- a/services/core/java/com/android/server/power/PreRebootLogger.java
+++ b/services/core/java/com/android/server/power/PreRebootLogger.java
@@ -16,6 +16,7 @@
package com.android.server.power;
+import android.annotation.DurationMillisLong;
import android.annotation.NonNull;
import android.content.Context;
import android.os.Environment;
@@ -23,7 +24,7 @@
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.provider.Settings;
+import android.provider.Settings.Global;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
@@ -34,6 +35,8 @@
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Provides utils to dump/wipe pre-reboot information.
@@ -46,10 +49,12 @@
private static final String[] SERVICES_TO_DUMP = {Context.ROLLBACK_SERVICE, "package"};
private static final Object sLock = new Object();
+ private static final long MAX_DUMP_TIME = TimeUnit.SECONDS.toMillis(20);
/**
* Process pre-reboot information. Dump pre-reboot information to {@link #PREREBOOT_DIR} if
- * enabled {@link Settings.Global#ADB_ENABLED}; wipe dumped information otherwise.
+ * enabled {@link Settings.Global#ADB_ENABLED} and having active staged session; wipe dumped
+ * information otherwise.
*/
static void log(Context context) {
log(context, getDumpDir());
@@ -57,28 +62,49 @@
@VisibleForTesting
static void log(Context context, @NonNull File dumpDir) {
- if (Settings.Global.getInt(
- context.getContentResolver(), Settings.Global.ADB_ENABLED, 0) == 1) {
- Slog.d(TAG, "Dumping pre-reboot information...");
- dump(dumpDir);
+ if (needDump(context)) {
+ dump(dumpDir, MAX_DUMP_TIME);
} else {
- Slog.d(TAG, "Wiping pre-reboot information...");
wipe(dumpDir);
}
}
- private static void dump(@NonNull File dumpDir) {
- synchronized (sLock) {
- for (String buffer : BUFFERS_TO_DUMP) {
- dumpLogsLocked(dumpDir, buffer);
+ private static boolean needDump(Context context) {
+ return Global.getInt(context.getContentResolver(), Global.ADB_ENABLED, 0) == 1
+ && !context.getPackageManager().getPackageInstaller()
+ .getActiveStagedSessions().isEmpty();
+ }
+
+ @VisibleForTesting
+ static void dump(@NonNull File dumpDir, @DurationMillisLong long maxWaitTime) {
+ Slog.d(TAG, "Dumping pre-reboot information...");
+ final AtomicBoolean done = new AtomicBoolean(false);
+ final Thread t = new Thread(() -> {
+ synchronized (sLock) {
+ for (String buffer : BUFFERS_TO_DUMP) {
+ dumpLogsLocked(dumpDir, buffer);
+ }
+ for (String service : SERVICES_TO_DUMP) {
+ dumpServiceLocked(dumpDir, service);
+ }
}
- for (String service : SERVICES_TO_DUMP) {
- dumpServiceLocked(dumpDir, service);
- }
+ done.set(true);
+ });
+ t.start();
+
+ try {
+ t.join(maxWaitTime);
+ } catch (InterruptedException e) {
+ Slog.e(TAG, "Failed to dump pre-reboot information due to interrupted", e);
+ }
+
+ if (!done.get()) {
+ Slog.w(TAG, "Failed to dump pre-reboot information due to timeout");
}
}
private static void wipe(@NonNull File dumpDir) {
+ Slog.d(TAG, "Wiping pre-reboot information...");
synchronized (sLock) {
for (File file : dumpDir.listFiles()) {
file.delete();
@@ -109,7 +135,7 @@
{"logcat", "-d", "-b", buffer, "-f", dumpFile.getAbsolutePath()};
Runtime.getRuntime().exec(cmdline).waitFor();
} catch (IOException | InterruptedException e) {
- Slog.d(TAG, "Dump system log buffer before reboot fail", e);
+ Slog.e(TAG, "Failed to dump system log buffer before reboot", e);
}
}
@@ -127,7 +153,7 @@
| ParcelFileDescriptor.MODE_WRITE_ONLY);
binder.dump(fd.getFileDescriptor(), ArrayUtils.emptyArray(String.class));
} catch (FileNotFoundException | RemoteException e) {
- Slog.d(TAG, String.format("Dump %s service before reboot fail", serviceName), e);
+ Slog.e(TAG, String.format("Failed to dump %s service before reboot", serviceName), e);
}
}
}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index c0c9b32..c2bae1a 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -191,7 +191,6 @@
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
@@ -257,21 +256,17 @@
@GuardedBy("mNotificationStatsLock")
private INotificationManager mNotificationManagerService;
- private final Object mProcessStatsLock = new Object();
- @GuardedBy("mProcessStatsLock")
+ @GuardedBy("mProcStatsLock")
private IProcessStats mProcessStatsService;
- private final Object mCpuTrackerLock = new Object();
- @GuardedBy("mCpuTrackerLock")
+ @GuardedBy("mProcessCpuTimeLock")
private ProcessCpuTracker mProcessCpuTracker;
- private final Object mDebugElapsedClockLock = new Object();
@GuardedBy("mDebugElapsedClockLock")
private long mDebugElapsedClockPreviousValue = 0;
@GuardedBy("mDebugElapsedClockLock")
private long mDebugElapsedClockPullCount = 0;
- private final Object mDebugFailingElapsedClockLock = new Object();
@GuardedBy("mDebugFailingElapsedClockLock")
private long mDebugFailingElapsedClockPreviousValue = 0;
@GuardedBy("mDebugFailingElapsedClockLock")
@@ -284,26 +279,40 @@
private TelephonyManager mTelephony;
private SubscriptionManager mSubscriptionManager;
+ @GuardedBy("mKernelWakelockLock")
private KernelWakelockReader mKernelWakelockReader;
+ @GuardedBy("mKernelWakelockLock")
private KernelWakelockStats mTmpWakelockStats;
+ @GuardedBy("mDiskIoLock")
private StoragedUidIoStatsReader mStoragedUidIoStatsReader;
+ @GuardedBy("mCpuTimePerFreqLock")
private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
// Disables throttler on CPU time readers.
+ @GuardedBy("mCpuTimePerUidLock")
private KernelCpuUidUserSysTimeReader mCpuUidUserSysTimeReader;
+ @GuardedBy("mCpuTimePerUidFreqLock")
private KernelCpuUidFreqTimeReader mCpuUidFreqTimeReader;
+ @GuardedBy("mCpuActiveTimeLock")
private KernelCpuUidActiveTimeReader mCpuUidActiveTimeReader;
+ @GuardedBy("mClusterTimeLock")
private KernelCpuUidClusterTimeReader mCpuUidClusterTimeReader;
+ @GuardedBy("mProcStatsLock")
private File mBaseDir;
+ @GuardedBy("mHealthHalLock")
private BatteryService.HealthServiceWrapper mHealthService;
@Nullable
+ @GuardedBy("mCpuTimePerThreadFreqLock")
private KernelCpuThreadReaderDiff mKernelCpuThreadReader;
+ private final Object mBatteryStatsHelperLock = new Object();
+ @GuardedBy("mBatteryStatsHelperLock")
private BatteryStatsHelper mBatteryStatsHelper = null;
+ @GuardedBy("mBatteryStatsHelperLock")
private long mBatteryStatsHelperTimestampMs = -MAX_BATTERY_STATS_HELPER_FREQUENCY_MS;
private StatsPullAtomCallbackImpl mStatsCallbackImpl;
@@ -311,19 +320,75 @@
private final Object mAppOpsSamplingRateLock = new Object();
@GuardedBy("mAppOpsSamplingRateLock")
private int mAppOpsSamplingRate = 0;
+ private final Object mDangerousAppOpsListLock = new Object();
+ @GuardedBy("mDangerousAppOpsListLock")
private final ArraySet<Integer> mDangerousAppOpsList = new ArraySet<>();
// Baselines that stores list of NetworkStats right after initializing, with associated
- // information. This is used to calculate difference when pulling
- // {Mobile|Wifi}BytesTransfer* atoms. Note that this is not thread-safe, and must
- // only be accessed on the background thread.
+ // information. This is used to calculate difference when pulling BytesTransfer atoms.
@NonNull
- private final List<NetworkStatsExt> mNetworkStatsBaselines = new ArrayList<>();
+ @GuardedBy("mDataBytesTransferLock")
+ private final ArrayList<NetworkStatsExt> mNetworkStatsBaselines = new ArrayList<>();
// Listener for monitoring subscriptions changed event.
private StatsSubscriptionsListener mStatsSubscriptionsListener;
// List that stores SubInfo of subscriptions that ever appeared since boot.
- private final CopyOnWriteArrayList<SubInfo> mHistoricalSubs = new CopyOnWriteArrayList<>();
+ @GuardedBy("mDataBytesTransferLock")
+ private final ArrayList<SubInfo> mHistoricalSubs = new ArrayList<>();
+
+ // Puller locks
+ private final Object mDataBytesTransferLock = new Object();
+ private final Object mBluetoothBytesTransferLock = new Object();
+ private final Object mKernelWakelockLock = new Object();
+ private final Object mCpuTimePerFreqLock = new Object();
+ private final Object mCpuTimePerUidLock = new Object();
+ private final Object mCpuTimePerUidFreqLock = new Object();
+ private final Object mCpuActiveTimeLock = new Object();
+ private final Object mCpuClusterTimeLock = new Object();
+ private final Object mWifiActivityInfoLock = new Object();
+ private final Object mModemActivityInfoLock = new Object();
+ private final Object mBluetoothActivityInfoLock = new Object();
+ private final Object mSystemElapsedRealtimeLock = new Object();
+ private final Object mSystemUptimeLock = new Object();
+ private final Object mProcessMemoryStateLock = new Object();
+ private final Object mProcessMemoryHighWaterMarkLock = new Object();
+ private final Object mProcessMemorySnapshotLock = new Object();
+ private final Object mSystemIonHeapSizeLock = new Object();
+ private final Object mIonHeapSizeLock = new Object();
+ private final Object mProcessSystemIonHeapSizeLock = new Object();
+ private final Object mTemperatureLock = new Object();
+ private final Object mCooldownDeviceLock = new Object();
+ private final Object mBinderCallsStatsLock = new Object();
+ private final Object mBinderCallsStatsExceptionsLock = new Object();
+ private final Object mLooperStatsLock = new Object();
+ private final Object mDiskStatsLock = new Object();
+ private final Object mDirectoryUsageLock = new Object();
+ private final Object mAppSizeLock = new Object();
+ private final Object mCategorySizeLock = new Object();
+ private final Object mNumBiometricsEnrolledLock = new Object();
+ private final Object mProcStatsLock = new Object();
+ private final Object mDiskIoLock = new Object();
+ private final Object mPowerProfileLock = new Object();
+ private final Object mProcessCpuTimeLock = new Object();
+ private final Object mCpuTimePerThreadFreqLock = new Object();
+ private final Object mDeviceCalculatedPowerUseLock = new Object();
+ private final Object mDeviceCalculatedPowerBlameUidLock = new Object();
+ private final Object mDeviceCalculatedPowerBlameOtherLock = new Object();
+ private final Object mDebugElapsedClockLock = new Object();
+ private final Object mDebugFailingElapsedClockLock = new Object();
+ private final Object mBuildInformationLock = new Object();
+ private final Object mRoleHolderLock = new Object();
+ private final Object mTimeZoneDataInfoLock = new Object();
+ private final Object mExternalStorageInfoLock = new Object();
+ private final Object mAppsOnExternalStorageInfoLock = new Object();
+ private final Object mFaceSettingsLock = new Object();
+ private final Object mAppOpsLock = new Object();
+ private final Object mRuntimeAppOpAccessMessageLock = new Object();
+ private final Object mNotificationRemoteViewsLock = new Object();
+ private final Object mDangerousPermissionStateLock = new Object();
+ private final Object mHealthHalLock = new Object();
+ private final Object mAttributedAppOpsLock = new Object();
+ private final Object mSettingsStatsLock = new Object();
public StatsPullAtomService(Context context) {
super(context);
@@ -353,123 +418,229 @@
case FrameworkStatsLog.MOBILE_BYTES_TRANSFER_BY_FG_BG:
case FrameworkStatsLog.BYTES_TRANSFER_BY_TAG_AND_METERED:
case FrameworkStatsLog.DATA_USAGE_BYTES_TRANSFER:
- return pullDataBytesTransfer(atomTag, data);
+ synchronized (mDataBytesTransferLock) {
+ return pullDataBytesTransferLocked(atomTag, data);
+ }
case FrameworkStatsLog.BLUETOOTH_BYTES_TRANSFER:
- return pullBluetoothBytesTransfer(atomTag, data);
+ synchronized (mBluetoothBytesTransferLock) {
+ return pullBluetoothBytesTransferLocked(atomTag, data);
+ }
case FrameworkStatsLog.KERNEL_WAKELOCK:
- return pullKernelWakelock(atomTag, data);
+ synchronized (mKernelWakelockLock) {
+ return pullKernelWakelockLocked(atomTag, data);
+ }
case FrameworkStatsLog.CPU_TIME_PER_FREQ:
- return pullCpuTimePerFreq(atomTag, data);
+ synchronized (mCpuTimePerFreqLock) {
+ return pullCpuTimePerFreqLocked(atomTag, data);
+ }
case FrameworkStatsLog.CPU_TIME_PER_UID:
- return pullCpuTimePerUid(atomTag, data);
+ synchronized (mCpuTimePerUidLock) {
+ return pullCpuTimePerUidLocked(atomTag, data);
+ }
case FrameworkStatsLog.CPU_TIME_PER_UID_FREQ:
- return pullCpuTimeperUidFreq(atomTag, data);
+ synchronized (mCpuTimePerUidFreqLock) {
+ return pullCpuTimePerUidFreqLocked(atomTag, data);
+ }
case FrameworkStatsLog.CPU_ACTIVE_TIME:
- return pullCpuActiveTime(atomTag, data);
+ synchronized (mCpuActiveTimeLock) {
+ return pullCpuActiveTimeLocked(atomTag, data);
+ }
case FrameworkStatsLog.CPU_CLUSTER_TIME:
- return pullCpuClusterTime(atomTag, data);
+ synchronized (mCpuClusterTimeLock) {
+ return pullCpuClusterTimeLocked(atomTag, data);
+ }
case FrameworkStatsLog.WIFI_ACTIVITY_INFO:
- return pullWifiActivityInfo(atomTag, data);
+ synchronized (mWifiActivityInfoLock) {
+ return pullWifiActivityInfoLocked(atomTag, data);
+ }
case FrameworkStatsLog.MODEM_ACTIVITY_INFO:
- return pullModemActivityInfo(atomTag, data);
+ synchronized (mModemActivityInfoLock) {
+ return pullModemActivityInfoLocked(atomTag, data);
+ }
case FrameworkStatsLog.BLUETOOTH_ACTIVITY_INFO:
- return pullBluetoothActivityInfo(atomTag, data);
+ synchronized (mBluetoothActivityInfoLock) {
+ return pullBluetoothActivityInfoLocked(atomTag, data);
+ }
case FrameworkStatsLog.SYSTEM_ELAPSED_REALTIME:
- return pullSystemElapsedRealtime(atomTag, data);
+ synchronized (mSystemElapsedRealtimeLock) {
+ return pullSystemElapsedRealtimeLocked(atomTag, data);
+ }
case FrameworkStatsLog.SYSTEM_UPTIME:
- return pullSystemUptime(atomTag, data);
+ synchronized (mSystemUptimeLock) {
+ return pullSystemUptimeLocked(atomTag, data);
+ }
case FrameworkStatsLog.PROCESS_MEMORY_STATE:
- return pullProcessMemoryState(atomTag, data);
+ synchronized (mProcessMemoryStateLock) {
+ return pullProcessMemoryStateLocked(atomTag, data);
+ }
case FrameworkStatsLog.PROCESS_MEMORY_HIGH_WATER_MARK:
- return pullProcessMemoryHighWaterMark(atomTag, data);
+ synchronized (mProcessMemoryHighWaterMarkLock) {
+ return pullProcessMemoryHighWaterMarkLocked(atomTag, data);
+ }
case FrameworkStatsLog.PROCESS_MEMORY_SNAPSHOT:
- return pullProcessMemorySnapshot(atomTag, data);
+ synchronized (mProcessMemorySnapshotLock) {
+ return pullProcessMemorySnapshotLocked(atomTag, data);
+ }
case FrameworkStatsLog.SYSTEM_ION_HEAP_SIZE:
- return pullSystemIonHeapSize(atomTag, data);
+ synchronized (mSystemIonHeapSizeLock) {
+ return pullSystemIonHeapSizeLocked(atomTag, data);
+ }
case FrameworkStatsLog.ION_HEAP_SIZE:
- return pullIonHeapSize(atomTag, data);
+ synchronized (mIonHeapSizeLock) {
+ return pullIonHeapSizeLocked(atomTag, data);
+ }
case FrameworkStatsLog.PROCESS_SYSTEM_ION_HEAP_SIZE:
- return pullProcessSystemIonHeapSize(atomTag, data);
+ synchronized (mProcessSystemIonHeapSizeLock) {
+ return pullProcessSystemIonHeapSizeLocked(atomTag, data);
+ }
case FrameworkStatsLog.TEMPERATURE:
- return pullTemperature(atomTag, data);
+ synchronized (mTemperatureLock) {
+ return pullTemperatureLocked(atomTag, data);
+ }
case FrameworkStatsLog.COOLING_DEVICE:
- return pullCooldownDevice(atomTag, data);
+ synchronized (mCooldownDeviceLock) {
+ return pullCooldownDeviceLocked(atomTag, data);
+ }
case FrameworkStatsLog.BINDER_CALLS:
- return pullBinderCallsStats(atomTag, data);
+ synchronized (mBinderCallsStatsLock) {
+ return pullBinderCallsStatsLocked(atomTag, data);
+ }
case FrameworkStatsLog.BINDER_CALLS_EXCEPTIONS:
- return pullBinderCallsStatsExceptions(atomTag, data);
+ synchronized (mBinderCallsStatsExceptionsLock) {
+ return pullBinderCallsStatsExceptionsLocked(atomTag, data);
+ }
case FrameworkStatsLog.LOOPER_STATS:
- return pullLooperStats(atomTag, data);
+ synchronized (mLooperStatsLock) {
+ return pullLooperStatsLocked(atomTag, data);
+ }
case FrameworkStatsLog.DISK_STATS:
- return pullDiskStats(atomTag, data);
+ synchronized (mDiskStatsLock) {
+ return pullDiskStatsLocked(atomTag, data);
+ }
case FrameworkStatsLog.DIRECTORY_USAGE:
- return pullDirectoryUsage(atomTag, data);
+ synchronized (mDirectoryUsageLock) {
+ return pullDirectoryUsageLocked(atomTag, data);
+ }
case FrameworkStatsLog.APP_SIZE:
- return pullAppSize(atomTag, data);
+ synchronized (mAppSizeLock) {
+ return pullAppSizeLocked(atomTag, data);
+ }
case FrameworkStatsLog.CATEGORY_SIZE:
- return pullCategorySize(atomTag, data);
+ synchronized (mCategorySizeLock) {
+ return pullCategorySizeLocked(atomTag, data);
+ }
case FrameworkStatsLog.NUM_FINGERPRINTS_ENROLLED:
- return pullNumBiometricsEnrolled(
- BiometricsProtoEnums.MODALITY_FINGERPRINT, atomTag, data);
+ synchronized (mNumBiometricsEnrolledLock) {
+ return pullNumBiometricsEnrolledLocked(
+ BiometricsProtoEnums.MODALITY_FINGERPRINT, atomTag, data);
+ }
case FrameworkStatsLog.NUM_FACES_ENROLLED:
- return pullNumBiometricsEnrolled(
- BiometricsProtoEnums.MODALITY_FACE, atomTag, data);
+ synchronized (mNumBiometricsEnrolledLock) {
+ return pullNumBiometricsEnrolledLocked(
+ BiometricsProtoEnums.MODALITY_FACE, atomTag, data);
+ }
case FrameworkStatsLog.PROC_STATS:
- return pullProcStats(ProcessStats.REPORT_ALL, atomTag, data);
+ synchronized (mProcStatsLock) {
+ return pullProcStatsLocked(ProcessStats.REPORT_ALL, atomTag, data);
+ }
case FrameworkStatsLog.PROC_STATS_PKG_PROC:
- return pullProcStats(ProcessStats.REPORT_PKG_PROC_STATS, atomTag, data);
+ synchronized (mProcStatsLock) {
+ return pullProcStatsLocked(ProcessStats.REPORT_PKG_PROC_STATS, atomTag,
+ data);
+ }
case FrameworkStatsLog.DISK_IO:
- return pullDiskIO(atomTag, data);
+ synchronized (mDiskIoLock) {
+ return pullDiskIOLocked(atomTag, data);
+ }
case FrameworkStatsLog.POWER_PROFILE:
- return pullPowerProfile(atomTag, data);
+ synchronized (mPowerProfileLock) {
+ return pullPowerProfileLocked(atomTag, data);
+ }
case FrameworkStatsLog.PROCESS_CPU_TIME:
- return pullProcessCpuTime(atomTag, data);
+ synchronized (mProcessCpuTimeLock) {
+ return pullProcessCpuTimeLocked(atomTag, data);
+ }
case FrameworkStatsLog.CPU_TIME_PER_THREAD_FREQ:
- return pullCpuTimePerThreadFreq(atomTag, data);
+ synchronized (mCpuTimePerThreadFreqLock) {
+ return pullCpuTimePerThreadFreqLocked(atomTag, data);
+ }
case FrameworkStatsLog.DEVICE_CALCULATED_POWER_USE:
- return pullDeviceCalculatedPowerUse(atomTag, data);
+ synchronized (mDeviceCalculatedPowerUseLock) {
+ return pullDeviceCalculatedPowerUseLocked(atomTag, data);
+ }
case FrameworkStatsLog.DEVICE_CALCULATED_POWER_BLAME_UID:
- return pullDeviceCalculatedPowerBlameUid(atomTag, data);
+ synchronized (mDeviceCalculatedPowerBlameUidLock) {
+ return pullDeviceCalculatedPowerBlameUidLocked(atomTag, data);
+ }
case FrameworkStatsLog.DEVICE_CALCULATED_POWER_BLAME_OTHER:
- return pullDeviceCalculatedPowerBlameOther(atomTag, data);
+ synchronized (mDeviceCalculatedPowerBlameOtherLock) {
+ return pullDeviceCalculatedPowerBlameOtherLocked(atomTag, data);
+ }
case FrameworkStatsLog.DEBUG_ELAPSED_CLOCK:
- return pullDebugElapsedClock(atomTag, data);
+ synchronized (mDebugElapsedClockLock) {
+ return pullDebugElapsedClockLocked(atomTag, data);
+ }
case FrameworkStatsLog.DEBUG_FAILING_ELAPSED_CLOCK:
- return pullDebugFailingElapsedClock(atomTag, data);
+ synchronized (mDebugFailingElapsedClockLock) {
+ return pullDebugFailingElapsedClockLocked(atomTag, data);
+ }
case FrameworkStatsLog.BUILD_INFORMATION:
- return pullBuildInformation(atomTag, data);
+ synchronized (mBuildInformationLock) {
+ return pullBuildInformationLocked(atomTag, data);
+ }
case FrameworkStatsLog.ROLE_HOLDER:
- return pullRoleHolder(atomTag, data);
+ synchronized (mRoleHolderLock) {
+ return pullRoleHolderLocked(atomTag, data);
+ }
case FrameworkStatsLog.DANGEROUS_PERMISSION_STATE:
- return pullDangerousPermissionState(atomTag, data);
- case FrameworkStatsLog.TIME_ZONE_DATA_INFO:
- return pullTimeZoneDataInfo(atomTag, data);
- case FrameworkStatsLog.EXTERNAL_STORAGE_INFO:
- return pullExternalStorageInfo(atomTag, data);
- case FrameworkStatsLog.APPS_ON_EXTERNAL_STORAGE_INFO:
- return pullAppsOnExternalStorageInfo(atomTag, data);
- case FrameworkStatsLog.FACE_SETTINGS:
- return pullFaceSettings(atomTag, data);
- case FrameworkStatsLog.APP_OPS:
- return pullAppOps(atomTag, data);
- case FrameworkStatsLog.RUNTIME_APP_OP_ACCESS:
- return pullRuntimeAppOpAccessMessage(atomTag, data);
- case FrameworkStatsLog.NOTIFICATION_REMOTE_VIEWS:
- return pullNotificationRemoteViews(atomTag, data);
case FrameworkStatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED:
- return pullDangerousPermissionState(atomTag, data);
+ synchronized (mDangerousPermissionStateLock) {
+ return pullDangerousPermissionStateLocked(atomTag, data);
+ }
+ case FrameworkStatsLog.TIME_ZONE_DATA_INFO:
+ synchronized (mTimeZoneDataInfoLock) {
+ return pullTimeZoneDataInfoLocked(atomTag, data);
+ }
+ case FrameworkStatsLog.EXTERNAL_STORAGE_INFO:
+ synchronized (mExternalStorageInfoLock) {
+ return pullExternalStorageInfoLocked(atomTag, data);
+ }
+ case FrameworkStatsLog.APPS_ON_EXTERNAL_STORAGE_INFO:
+ synchronized (mAppsOnExternalStorageInfoLock) {
+ return pullAppsOnExternalStorageInfoLocked(atomTag, data);
+ }
+ case FrameworkStatsLog.FACE_SETTINGS:
+ synchronized (mFaceSettingsLock) {
+ return pullFaceSettingsLocked(atomTag, data);
+ }
+ case FrameworkStatsLog.APP_OPS:
+ synchronized (mAppOpsLock) {
+ return pullAppOpsLocked(atomTag, data);
+ }
+ case FrameworkStatsLog.RUNTIME_APP_OP_ACCESS:
+ synchronized (mRuntimeAppOpAccessMessageLock) {
+ return pullRuntimeAppOpAccessMessageLocked(atomTag, data);
+ }
+ case FrameworkStatsLog.NOTIFICATION_REMOTE_VIEWS:
+ synchronized (mNotificationRemoteViewsLock) {
+ return pullNotificationRemoteViewsLocked(atomTag, data);
+ }
case FrameworkStatsLog.BATTERY_LEVEL:
case FrameworkStatsLog.REMAINING_BATTERY_CAPACITY:
case FrameworkStatsLog.FULL_BATTERY_CAPACITY:
case FrameworkStatsLog.BATTERY_VOLTAGE:
case FrameworkStatsLog.BATTERY_CYCLE_COUNT:
- return pullHealthHal(atomTag, data);
+ synchronized (mHealthHalLock) {
+ return pullHealthHalLocked(atomTag, data);
+ }
case FrameworkStatsLog.ATTRIBUTED_APP_OPS:
- return pullAttributedAppOps(atomTag, data);
+ synchronized (mAttributedAppOpsLock) {
+ return pullAttributedAppOpsLocked(atomTag, data);
+ }
case FrameworkStatsLog.SETTING_SNAPSHOT:
- return pullSettingsStats(atomTag, data);
- case FrameworkStatsLog.DISPLAY_WAKE_REASON:
- return pullDisplayWakeStats(atomTag, data);
+ synchronized (mSettingsStatsLock) {
+ return pullSettingsStatsLocked(atomTag, data);
+ }
default:
throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
}
@@ -500,6 +671,8 @@
}
}
+ // We do not hold locks within this function because it is guaranteed to be called before the
+ // pullers are ever run, as the pullers are not yet registered with statsd.
void initializePullersState() {
// Get Context Managers
mStatsManager = (StatsManager) mContext.getSystemService(Context.STATS_MANAGER);
@@ -515,6 +688,7 @@
// Initialize PROC_STATS
mBaseDir = new File(SystemServiceManager.ensureSystemDir(), "stats_pull");
+ mBaseDir.mkdirs();
// Disables throttler on CPU time readers.
mCpuUidUserSysTimeReader = new KernelCpuUidUserSysTimeReader(false);
@@ -542,9 +716,6 @@
mKernelCpuThreadReader =
KernelCpuThreadReaderSettingsObserver.getSettingsModifiedReader(mContext);
- // Used by PROC_STATS and PROC_STATS_PKG_PROC atoms
- mBaseDir.mkdirs();
-
// Initialize HealthService
mHealthService = new BatteryService.HealthServiceWrapper();
try {
@@ -656,7 +827,6 @@
registerBatteryVoltage();
registerBatteryCycleCount();
registerSettingsStats();
- registerDisplayWakeStats();
}
private void initAndRegisterNetworkStatsPullers() {
@@ -783,7 +953,7 @@
}
private IProcessStats getIProcessStatsService() {
- synchronized (mProcessStatsLock) {
+ synchronized (mProcStatsLock) {
if (mProcessStatsService == null) {
mProcessStatsService = IProcessStats.Stub.asInterface(
ServiceManager.getService(ProcessStats.SERVICE_NAME));
@@ -791,7 +961,7 @@
if (mProcessStatsService != null) {
try {
mProcessStatsService.asBinder().linkToDeath(() -> {
- synchronized (mProcessStatsLock) {
+ synchronized (mProcStatsLock) {
mProcessStatsService = null;
}
}, /* flags */ 0);
@@ -882,8 +1052,7 @@
return ret;
}
- private int pullDataBytesTransfer(
- int atomTag, @NonNull List<StatsEvent> pulledData) {
+ private int pullDataBytesTransferLocked(int atomTag, @NonNull List<StatsEvent> pulledData) {
final List<NetworkStatsExt> current = collectNetworkStatsSnapshotForAtom(atomTag);
if (current == null) {
@@ -1237,12 +1406,11 @@
return null;
}
- private synchronized BluetoothActivityEnergyInfo fetchBluetoothData() {
- // TODO: Investigate whether the synchronized keyword is needed.
+ private BluetoothActivityEnergyInfo fetchBluetoothData() {
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter != null) {
- SynchronousResultReceiver bluetoothReceiver = new SynchronousResultReceiver(
- "bluetooth");
+ SynchronousResultReceiver bluetoothReceiver =
+ new SynchronousResultReceiver("bluetooth");
adapter.requestControllerActivityEnergyInfo(bluetoothReceiver);
return awaitControllerInfo(bluetoothReceiver);
} else {
@@ -1251,7 +1419,7 @@
}
}
- int pullBluetoothBytesTransfer(int atomTag, List<StatsEvent> pulledData) {
+ int pullBluetoothBytesTransferLocked(int atomTag, List<StatsEvent> pulledData) {
BluetoothActivityEnergyInfo info = fetchBluetoothData();
if (info == null || info.getUidTraffic() == null) {
return StatsManager.PULL_SKIP;
@@ -1279,7 +1447,7 @@
);
}
- int pullKernelWakelock(int atomTag, List<StatsEvent> pulledData) {
+ int pullKernelWakelockLocked(int atomTag, List<StatsEvent> pulledData) {
final KernelWakelockStats wakelockStats =
mKernelWakelockReader.readKernelWakelockStats(mTmpWakelockStats);
for (Map.Entry<String, KernelWakelockStats.Entry> ent : wakelockStats.entrySet()) {
@@ -1310,7 +1478,7 @@
);
}
- int pullCpuTimePerFreq(int atomTag, List<StatsEvent> pulledData) {
+ int pullCpuTimePerFreqLocked(int atomTag, List<StatsEvent> pulledData) {
for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
long[] clusterTimeMs = mKernelCpuSpeedReaders[cluster].readAbsolute();
if (clusterTimeMs != null) {
@@ -1341,7 +1509,7 @@
);
}
- int pullCpuTimePerUid(int atomTag, List<StatsEvent> pulledData) {
+ int pullCpuTimePerUidLocked(int atomTag, List<StatsEvent> pulledData) {
mCpuUidUserSysTimeReader.readAbsolute((uid, timesUs) -> {
long userTimeUs = timesUs[0], systemTimeUs = timesUs[1];
StatsEvent e = StatsEvent.newBuilder()
@@ -1371,7 +1539,7 @@
);
}
- int pullCpuTimeperUidFreq(int atomTag, List<StatsEvent> pulledData) {
+ int pullCpuTimePerUidFreqLocked(int atomTag, List<StatsEvent> pulledData) {
mCpuUidFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> {
for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
if (cpuFreqTimeMs[freqIndex] != 0) {
@@ -1404,7 +1572,7 @@
);
}
- int pullCpuActiveTime(int atomTag, List<StatsEvent> pulledData) {
+ int pullCpuActiveTimeLocked(int atomTag, List<StatsEvent> pulledData) {
mCpuUidActiveTimeReader.readAbsolute((uid, cpuActiveTimesMs) -> {
StatsEvent e = StatsEvent.newBuilder()
.setAtomId(atomTag)
@@ -1432,7 +1600,7 @@
);
}
- int pullCpuClusterTime(int atomTag, List<StatsEvent> pulledData) {
+ int pullCpuClusterTimeLocked(int atomTag, List<StatsEvent> pulledData) {
mCpuUidClusterTimeReader.readAbsolute((uid, cpuClusterTimesMs) -> {
for (int i = 0; i < cpuClusterTimesMs.length; i++) {
StatsEvent e = StatsEvent.newBuilder()
@@ -1458,7 +1626,7 @@
);
}
- int pullWifiActivityInfo(int atomTag, List<StatsEvent> pulledData) {
+ int pullWifiActivityInfoLocked(int atomTag, List<StatsEvent> pulledData) {
long token = Binder.clearCallingIdentity();
try {
SynchronousResultReceiver wifiReceiver = new SynchronousResultReceiver("wifi");
@@ -1510,7 +1678,7 @@
);
}
- int pullModemActivityInfo(int atomTag, List<StatsEvent> pulledData) {
+ int pullModemActivityInfoLocked(int atomTag, List<StatsEvent> pulledData) {
long token = Binder.clearCallingIdentity();
try {
SynchronousResultReceiver modemReceiver = new SynchronousResultReceiver("telephony");
@@ -1548,7 +1716,7 @@
);
}
- int pullBluetoothActivityInfo(int atomTag, List<StatsEvent> pulledData) {
+ int pullBluetoothActivityInfoLocked(int atomTag, List<StatsEvent> pulledData) {
BluetoothActivityEnergyInfo info = fetchBluetoothData();
if (info == null) {
return StatsManager.PULL_SKIP;
@@ -1580,7 +1748,7 @@
);
}
- int pullSystemElapsedRealtime(int atomTag, List<StatsEvent> pulledData) {
+ int pullSystemElapsedRealtimeLocked(int atomTag, List<StatsEvent> pulledData) {
StatsEvent e = StatsEvent.newBuilder()
.setAtomId(atomTag)
.writeLong(SystemClock.elapsedRealtime())
@@ -1599,7 +1767,7 @@
);
}
- int pullSystemUptime(int atomTag, List<StatsEvent> pulledData) {
+ int pullSystemUptimeLocked(int atomTag, List<StatsEvent> pulledData) {
StatsEvent e = StatsEvent.newBuilder()
.setAtomId(atomTag)
.writeLong(SystemClock.uptimeMillis())
@@ -1621,7 +1789,7 @@
);
}
- int pullProcessMemoryState(int atomTag, List<StatsEvent> pulledData) {
+ int pullProcessMemoryStateLocked(int atomTag, List<StatsEvent> pulledData) {
List<ProcessMemoryState> processMemoryStates =
LocalServices.getService(ActivityManagerInternal.class)
.getMemoryStateForProcesses();
@@ -1665,7 +1833,7 @@
);
}
- int pullProcessMemoryHighWaterMark(int atomTag, List<StatsEvent> pulledData) {
+ int pullProcessMemoryHighWaterMarkLocked(int atomTag, List<StatsEvent> pulledData) {
List<ProcessMemoryState> managedProcessList =
LocalServices.getService(ActivityManagerInternal.class)
.getMemoryStateForProcesses();
@@ -1720,7 +1888,7 @@
);
}
- int pullProcessMemorySnapshot(int atomTag, List<StatsEvent> pulledData) {
+ int pullProcessMemorySnapshotLocked(int atomTag, List<StatsEvent> pulledData) {
List<ProcessMemoryState> managedProcessList =
LocalServices.getService(ActivityManagerInternal.class)
.getMemoryStateForProcesses();
@@ -1782,7 +1950,7 @@
);
}
- int pullSystemIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
+ int pullSystemIonHeapSizeLocked(int atomTag, List<StatsEvent> pulledData) {
final long systemIonHeapSizeInBytes = readSystemIonHeapSizeFromDebugfs();
StatsEvent e = StatsEvent.newBuilder()
.setAtomId(atomTag)
@@ -1805,7 +1973,7 @@
);
}
- int pullIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
+ int pullIonHeapSizeLocked(int atomTag, List<StatsEvent> pulledData) {
int ionHeapSizeInKilobytes = (int) getIonHeapsSizeKb();
StatsEvent e = StatsEvent.newBuilder()
.setAtomId(atomTag)
@@ -1825,7 +1993,7 @@
);
}
- int pullProcessSystemIonHeapSize(int atomTag, List<StatsEvent> pulledData) {
+ int pullProcessSystemIonHeapSizeLocked(int atomTag, List<StatsEvent> pulledData) {
List<IonAllocations> result = readProcessSystemIonHeapSizesFromDebugfs();
for (IonAllocations allocations : result) {
StatsEvent e = StatsEvent.newBuilder()
@@ -1852,7 +2020,7 @@
);
}
- int pullTemperature(int atomTag, List<StatsEvent> pulledData) {
+ int pullTemperatureLocked(int atomTag, List<StatsEvent> pulledData) {
IThermalService thermalService = getIThermalService();
if (thermalService == null) {
return StatsManager.PULL_SKIP;
@@ -1890,7 +2058,7 @@
);
}
- int pullCooldownDevice(int atomTag, List<StatsEvent> pulledData) {
+ int pullCooldownDeviceLocked(int atomTag, List<StatsEvent> pulledData) {
IThermalService thermalService = getIThermalService();
if (thermalService == null) {
return StatsManager.PULL_SKIP;
@@ -1930,7 +2098,7 @@
);
}
- int pullBinderCallsStats(int atomTag, List<StatsEvent> pulledData) {
+ int pullBinderCallsStatsLocked(int atomTag, List<StatsEvent> pulledData) {
BinderCallsStatsService.Internal binderStats =
LocalServices.getService(BinderCallsStatsService.Internal.class);
if (binderStats == null) {
@@ -1974,7 +2142,7 @@
);
}
- int pullBinderCallsStatsExceptions(int atomTag, List<StatsEvent> pulledData) {
+ int pullBinderCallsStatsExceptionsLocked(int atomTag, List<StatsEvent> pulledData) {
BinderCallsStatsService.Internal binderStats =
LocalServices.getService(BinderCallsStatsService.Internal.class);
if (binderStats == null) {
@@ -2009,7 +2177,7 @@
);
}
- int pullLooperStats(int atomTag, List<StatsEvent> pulledData) {
+ int pullLooperStatsLocked(int atomTag, List<StatsEvent> pulledData) {
LooperStats looperStats = LocalServices.getService(LooperStats.class);
if (looperStats == null) {
return StatsManager.PULL_SKIP;
@@ -2052,7 +2220,7 @@
);
}
- int pullDiskStats(int atomTag, List<StatsEvent> pulledData) {
+ int pullDiskStatsLocked(int atomTag, List<StatsEvent> pulledData) {
// Run a quick-and-dirty performance test: write 512 bytes
byte[] junk = new byte[512];
for (int i = 0; i < junk.length; i++) junk[i] = (byte) i; // Write nonzero bytes
@@ -2118,7 +2286,7 @@
);
}
- int pullDirectoryUsage(int atomTag, List<StatsEvent> pulledData) {
+ int pullDirectoryUsageLocked(int atomTag, List<StatsEvent> pulledData) {
StatFs statFsData = new StatFs(Environment.getDataDirectory().getAbsolutePath());
StatFs statFsSystem = new StatFs(Environment.getRootDirectory().getAbsolutePath());
StatFs statFsCache = new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath());
@@ -2159,7 +2327,7 @@
);
}
- int pullAppSize(int atomTag, List<StatsEvent> pulledData) {
+ int pullAppSizeLocked(int atomTag, List<StatsEvent> pulledData) {
try {
String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH);
JSONObject json = new JSONObject(jsonStr);
@@ -2203,7 +2371,7 @@
);
}
- int pullCategorySize(int atomTag, List<StatsEvent> pulledData) {
+ int pullCategorySizeLocked(int atomTag, List<StatsEvent> pulledData) {
try {
String jsonStr = IoUtils.readFileAsString(DiskStatsLoggingService.DUMPSYS_CACHE_PATH);
JSONObject json = new JSONObject(jsonStr);
@@ -2317,7 +2485,8 @@
);
}
- private int pullNumBiometricsEnrolled(int modality, int atomTag, List<StatsEvent> pulledData) {
+ private int pullNumBiometricsEnrolledLocked(int modality, int atomTag,
+ List<StatsEvent> pulledData) {
final PackageManager pm = mContext.getPackageManager();
FingerprintManager fingerprintManager = null;
FaceManager faceManager = null;
@@ -2385,43 +2554,41 @@
);
}
- private int pullProcStats(int section, int atomTag, List<StatsEvent> pulledData) {
+ private int pullProcStatsLocked(int section, int atomTag, List<StatsEvent> pulledData) {
IProcessStats processStatsService = getIProcessStatsService();
if (processStatsService == null) {
return StatsManager.PULL_SKIP;
}
- synchronized (mProcessStatsLock) {
- final long token = Binder.clearCallingIdentity();
- try {
- // force procstats to flush & combine old files into one store
- long lastHighWaterMark = readProcStatsHighWaterMark(section);
- List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
+ final long token = Binder.clearCallingIdentity();
+ try {
+ // force procstats to flush & combine old files into one store
+ long lastHighWaterMark = readProcStatsHighWaterMark(section);
+ List<ParcelFileDescriptor> statsFiles = new ArrayList<>();
- ProcessStats procStats = new ProcessStats(false);
- long highWaterMark = processStatsService.getCommittedStatsMerged(
- lastHighWaterMark, section, true, statsFiles, procStats);
+ ProcessStats procStats = new ProcessStats(false);
+ long highWaterMark = processStatsService.getCommittedStatsMerged(
+ lastHighWaterMark, section, true, statsFiles, procStats);
- // aggregate the data together for westworld consumption
- ProtoOutputStream proto = new ProtoOutputStream();
- procStats.dumpAggregatedProtoForStatsd(proto);
+ // aggregate the data together for westworld consumption
+ ProtoOutputStream proto = new ProtoOutputStream();
+ procStats.dumpAggregatedProtoForStatsd(proto);
- StatsEvent e = StatsEvent.newBuilder()
- .setAtomId(atomTag)
- .writeByteArray(proto.getBytes())
- .build();
- pulledData.add(e);
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeByteArray(proto.getBytes())
+ .build();
+ pulledData.add(e);
- new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + lastHighWaterMark)
- .delete();
- new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + highWaterMark)
- .createNewFile();
- } catch (RemoteException | IOException e) {
- Slog.e(TAG, "Getting procstats failed: ", e);
- return StatsManager.PULL_SKIP;
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + lastHighWaterMark)
+ .delete();
+ new File(mBaseDir.getAbsolutePath() + "/" + section + "_" + highWaterMark)
+ .createNewFile();
+ } catch (RemoteException | IOException e) {
+ Slog.e(TAG, "Getting procstats failed: ", e);
+ return StatsManager.PULL_SKIP;
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
return StatsManager.PULL_SUCCESS;
}
@@ -2461,7 +2628,7 @@
);
}
- int pullDiskIO(int atomTag, List<StatsEvent> pulledData) {
+ int pullDiskIOLocked(int atomTag, List<StatsEvent> pulledData) {
mStoragedUidIoStatsReader.readAbsolute((uid, fgCharsRead, fgCharsWrite, fgBytesRead,
fgBytesWrite, bgCharsRead, bgCharsWrite, bgBytesRead, bgBytesWrite,
fgFsync, bgFsync) -> {
@@ -2495,7 +2662,7 @@
);
}
- int pullPowerProfile(int atomTag, List<StatsEvent> pulledData) {
+ int pullPowerProfileLocked(int atomTag, List<StatsEvent> pulledData) {
PowerProfile powerProfile = new PowerProfile(mContext);
ProtoOutputStream proto = new ProtoOutputStream();
powerProfile.dumpDebug(proto);
@@ -2522,25 +2689,23 @@
);
}
- int pullProcessCpuTime(int atomTag, List<StatsEvent> pulledData) {
- synchronized (mCpuTrackerLock) {
- if (mProcessCpuTracker == null) {
- mProcessCpuTracker = new ProcessCpuTracker(false);
- mProcessCpuTracker.init();
- }
- mProcessCpuTracker.update();
- for (int i = 0; i < mProcessCpuTracker.countStats(); i++) {
- ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
- StatsEvent e = StatsEvent.newBuilder()
- .setAtomId(atomTag)
- .writeInt(st.uid)
- .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
- .writeString(st.name)
- .writeLong(st.base_utime)
- .writeLong(st.base_stime)
- .build();
- pulledData.add(e);
- }
+ int pullProcessCpuTimeLocked(int atomTag, List<StatsEvent> pulledData) {
+ if (mProcessCpuTracker == null) {
+ mProcessCpuTracker = new ProcessCpuTracker(false);
+ mProcessCpuTracker.init();
+ }
+ mProcessCpuTracker.update();
+ for (int i = 0; i < mProcessCpuTracker.countStats(); i++) {
+ ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i);
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeInt(st.uid)
+ .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
+ .writeString(st.name)
+ .writeLong(st.base_utime)
+ .writeLong(st.base_stime)
+ .build();
+ pulledData.add(e);
}
return StatsManager.PULL_SUCCESS;
}
@@ -2558,7 +2723,7 @@
);
}
- int pullCpuTimePerThreadFreq(int atomTag, List<StatsEvent> pulledData) {
+ int pullCpuTimePerThreadFreqLocked(int atomTag, List<StatsEvent> pulledData) {
if (this.mKernelCpuThreadReader == null) {
Slog.e(TAG, "mKernelCpuThreadReader is null");
return StatsManager.PULL_SKIP;
@@ -2617,23 +2782,27 @@
}
private BatteryStatsHelper getBatteryStatsHelper() {
- if (mBatteryStatsHelper == null) {
- final long callingToken = Binder.clearCallingIdentity();
- try {
- // clearCallingIdentity required for BatteryStatsHelper.checkWifiOnly().
- mBatteryStatsHelper = new BatteryStatsHelper(mContext, false);
- } finally {
- Binder.restoreCallingIdentity(callingToken);
+ synchronized (mBatteryStatsHelperLock) {
+ if (mBatteryStatsHelper == null) {
+ final long callingToken = Binder.clearCallingIdentity();
+ try {
+ // clearCallingIdentity required for BatteryStatsHelper.checkWifiOnly().
+ mBatteryStatsHelper = new BatteryStatsHelper(mContext, false);
+ } finally {
+ Binder.restoreCallingIdentity(callingToken);
+ }
+ mBatteryStatsHelper.create((Bundle) null);
}
- mBatteryStatsHelper.create((Bundle) null);
- }
- long currentTime = SystemClock.elapsedRealtime();
- if (currentTime - mBatteryStatsHelperTimestampMs >= MAX_BATTERY_STATS_HELPER_FREQUENCY_MS) {
- // Load BatteryStats and do all the calculations.
- mBatteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.USER_ALL);
- // Calculations are done so we don't need to save the raw BatteryStats data in RAM.
- mBatteryStatsHelper.clearStats();
- mBatteryStatsHelperTimestampMs = currentTime;
+ long currentTime = SystemClock.elapsedRealtime();
+ if (currentTime - mBatteryStatsHelperTimestampMs
+ >= MAX_BATTERY_STATS_HELPER_FREQUENCY_MS) {
+ // Load BatteryStats and do all the calculations.
+ mBatteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED,
+ UserHandle.USER_ALL);
+ // Calculations are done so we don't need to save the raw BatteryStats data in RAM.
+ mBatteryStatsHelper.clearStats();
+ mBatteryStatsHelperTimestampMs = currentTime;
+ }
}
return mBatteryStatsHelper;
}
@@ -2652,7 +2821,7 @@
);
}
- int pullDeviceCalculatedPowerUse(int atomTag, List<StatsEvent> pulledData) {
+ int pullDeviceCalculatedPowerUseLocked(int atomTag, List<StatsEvent> pulledData) {
BatteryStatsHelper bsHelper = getBatteryStatsHelper();
StatsEvent e = StatsEvent.newBuilder()
.setAtomId(atomTag)
@@ -2672,7 +2841,7 @@
);
}
- int pullDeviceCalculatedPowerBlameUid(int atomTag, List<StatsEvent> pulledData) {
+ int pullDeviceCalculatedPowerBlameUidLocked(int atomTag, List<StatsEvent> pulledData) {
final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
if (sippers == null) {
return StatsManager.PULL_SKIP;
@@ -2703,7 +2872,7 @@
);
}
- int pullDeviceCalculatedPowerBlameOther(int atomTag, List<StatsEvent> pulledData) {
+ int pullDeviceCalculatedPowerBlameOtherLocked(int atomTag, List<StatsEvent> pulledData) {
final List<BatterySipper> sippers = getBatteryStatsHelper().getUsageList();
if (sippers == null) {
return StatsManager.PULL_SKIP;
@@ -2739,41 +2908,37 @@
);
}
- int pullDebugElapsedClock(int atomTag, List<StatsEvent> pulledData) {
+ int pullDebugElapsedClockLocked(int atomTag, List<StatsEvent> pulledData) {
final long elapsedMillis = SystemClock.elapsedRealtime();
+ final long clockDiffMillis = mDebugElapsedClockPreviousValue == 0
+ ? 0 : elapsedMillis - mDebugElapsedClockPreviousValue;
- synchronized (mDebugElapsedClockLock) {
- final long clockDiffMillis = mDebugElapsedClockPreviousValue == 0
- ? 0 : elapsedMillis - mDebugElapsedClockPreviousValue;
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeLong(mDebugElapsedClockPullCount)
+ .writeLong(elapsedMillis)
+ // Log it twice to be able to test multi-value aggregation from ValueMetric.
+ .writeLong(elapsedMillis)
+ .writeLong(clockDiffMillis)
+ .writeInt(1 /* always set */)
+ .build();
+ pulledData.add(e);
- StatsEvent e = StatsEvent.newBuilder()
+ if (mDebugElapsedClockPullCount % 2 == 1) {
+ StatsEvent e2 = StatsEvent.newBuilder()
.setAtomId(atomTag)
.writeLong(mDebugElapsedClockPullCount)
.writeLong(elapsedMillis)
// Log it twice to be able to test multi-value aggregation from ValueMetric.
.writeLong(elapsedMillis)
.writeLong(clockDiffMillis)
- .writeInt(1 /* always set */)
+ .writeInt(2 /* set on odd pulls */)
.build();
- pulledData.add(e);
-
- if (mDebugElapsedClockPullCount % 2 == 1) {
- StatsEvent e2 = StatsEvent.newBuilder()
- .setAtomId(atomTag)
- .writeLong(mDebugElapsedClockPullCount)
- .writeLong(elapsedMillis)
- // Log it twice to be able to test multi-value aggregation from ValueMetric.
- .writeLong(elapsedMillis)
- .writeLong(clockDiffMillis)
- .writeInt(2 /* set on odd pulls */)
- .build();
- pulledData.add(e2);
- }
-
- mDebugElapsedClockPullCount++;
- mDebugElapsedClockPreviousValue = elapsedMillis;
+ pulledData.add(e2);
}
+ mDebugElapsedClockPullCount++;
+ mDebugElapsedClockPreviousValue = elapsedMillis;
return StatsManager.PULL_SUCCESS;
}
@@ -2790,31 +2955,27 @@
);
}
- int pullDebugFailingElapsedClock(int atomTag, List<StatsEvent> pulledData) {
+ int pullDebugFailingElapsedClockLocked(int atomTag, List<StatsEvent> pulledData) {
final long elapsedMillis = SystemClock.elapsedRealtime();
-
- synchronized (mDebugFailingElapsedClockLock) {
- // Fails every 5 buckets.
- if (mDebugFailingElapsedClockPullCount++ % 5 == 0) {
- mDebugFailingElapsedClockPreviousValue = elapsedMillis;
- Slog.e(TAG, "Failing debug elapsed clock");
- return StatsManager.PULL_SKIP;
- }
-
- StatsEvent e = StatsEvent.newBuilder()
- .setAtomId(atomTag)
- .writeLong(mDebugFailingElapsedClockPullCount)
- .writeLong(elapsedMillis)
- // Log it twice to be able to test multi-value aggregation from ValueMetric.
- .writeLong(elapsedMillis)
- .writeLong(mDebugFailingElapsedClockPreviousValue == 0
- ? 0 : elapsedMillis - mDebugFailingElapsedClockPreviousValue)
- .build();
- pulledData.add(e);
-
+ // Fails every 5 buckets.
+ if (mDebugFailingElapsedClockPullCount++ % 5 == 0) {
mDebugFailingElapsedClockPreviousValue = elapsedMillis;
+ Slog.e(TAG, "Failing debug elapsed clock");
+ return StatsManager.PULL_SKIP;
}
+ StatsEvent e = StatsEvent.newBuilder()
+ .setAtomId(atomTag)
+ .writeLong(mDebugFailingElapsedClockPullCount)
+ .writeLong(elapsedMillis)
+ // Log it twice to be able to test multi-value aggregation from ValueMetric.
+ .writeLong(elapsedMillis)
+ .writeLong(mDebugFailingElapsedClockPreviousValue == 0
+ ? 0 : elapsedMillis - mDebugFailingElapsedClockPreviousValue)
+ .build();
+ pulledData.add(e);
+
+ mDebugFailingElapsedClockPreviousValue = elapsedMillis;
return StatsManager.PULL_SUCCESS;
}
@@ -2828,7 +2989,7 @@
);
}
- int pullBuildInformation(int atomTag, List<StatsEvent> pulledData) {
+ int pullBuildInformationLocked(int atomTag, List<StatsEvent> pulledData) {
StatsEvent e = StatsEvent.newBuilder()
.setAtomId(atomTag)
.writeString(Build.FINGERPRINT)
@@ -2856,7 +3017,7 @@
}
// Add a RoleHolder atom for each package that holds a role.
- int pullRoleHolder(int atomTag, List<StatsEvent> pulledData) {
+ int pullRoleHolderLocked(int atomTag, List<StatsEvent> pulledData) {
long callingToken = Binder.clearCallingIdentity();
try {
PackageManager pm = mContext.getPackageManager();
@@ -2914,7 +3075,7 @@
);
}
- int pullDangerousPermissionState(int atomTag, List<StatsEvent> pulledData) {
+ int pullDangerousPermissionStateLocked(int atomTag, List<StatsEvent> pulledData) {
final long token = Binder.clearCallingIdentity();
float samplingRate = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_PERMISSIONS,
DANGEROUS_PERMISSION_STATE_SAMPLE_RATE, 0.02f);
@@ -3007,7 +3168,7 @@
);
}
- int pullTimeZoneDataInfo(int atomTag, List<StatsEvent> pulledData) {
+ int pullTimeZoneDataInfoLocked(int atomTag, List<StatsEvent> pulledData) {
String tzDbVersion = "Unknown";
try {
tzDbVersion = android.icu.util.TimeZone.getTZDataVersion();
@@ -3034,7 +3195,7 @@
);
}
- int pullExternalStorageInfo(int atomTag, List<StatsEvent> pulledData) {
+ int pullExternalStorageInfoLocked(int atomTag, List<StatsEvent> pulledData) {
if (mStorageManager == null) {
return StatsManager.PULL_SKIP;
}
@@ -3084,7 +3245,7 @@
);
}
- int pullAppsOnExternalStorageInfo(int atomTag, List<StatsEvent> pulledData) {
+ int pullAppsOnExternalStorageInfoLocked(int atomTag, List<StatsEvent> pulledData) {
if (mStorageManager == null) {
return StatsManager.PULL_SKIP;
}
@@ -3140,7 +3301,7 @@
);
}
- int pullFaceSettings(int atomTag, List<StatsEvent> pulledData) {
+ int pullFaceSettingsLocked(int atomTag, List<StatsEvent> pulledData) {
final long callingToken = Binder.clearCallingIdentity();
try {
List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
@@ -3222,7 +3383,7 @@
}
}
- int pullAppOps(int atomTag, List<StatsEvent> pulledData) {
+ int pullAppOpsLocked(int atomTag, List<StatsEvent> pulledData) {
final long token = Binder.clearCallingIdentity();
try {
AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
@@ -3299,7 +3460,7 @@
);
}
- int pullAttributedAppOps(int atomTag, List<StatsEvent> pulledData) {
+ int pullAttributedAppOpsLocked(int atomTag, List<StatsEvent> pulledData) {
final long token = Binder.clearCallingIdentity();
try {
AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
@@ -3358,7 +3519,7 @@
CompletableFuture<HistoricalOps> ops = new CompletableFuture<>();
HistoricalOpsRequest histOpsRequest =
new HistoricalOpsRequest.Builder(
- Instant.now().minus(1, ChronoUnit.DAYS).toEpochMilli(),
+ Math.max(Instant.now().minus(1, ChronoUnit.DAYS).toEpochMilli(), 0),
Long.MAX_VALUE).setFlags(
OP_FLAGS_PULLED).build();
appOps.getHistoricalOps(histOpsRequest, AsyncTask.THREAD_POOL_EXECUTOR, ops::complete);
@@ -3377,7 +3538,9 @@
}
int estimatedSamplingRate = (int) constrain(
appOpsTargetCollectionSize * 100 / estimatedSize, 0, 100);
- mAppOpsSamplingRate = min(mAppOpsSamplingRate, estimatedSamplingRate);
+ synchronized (mAppOpsSamplingRateLock) {
+ mAppOpsSamplingRate = min(mAppOpsSamplingRate, estimatedSamplingRate);
+ }
}
private List<AppOpEntry> processHistoricalOps(
@@ -3420,7 +3583,7 @@
}
}
- int pullRuntimeAppOpAccessMessage(int atomTag, List<StatsEvent> pulledData) {
+ int pullRuntimeAppOpAccessMessageLocked(int atomTag, List<StatsEvent> pulledData) {
final long token = Binder.clearCallingIdentity();
try {
AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
@@ -3507,7 +3670,7 @@
);
}
- int pullNotificationRemoteViews(int atomTag, List<StatsEvent> pulledData) {
+ int pullNotificationRemoteViewsLocked(int atomTag, List<StatsEvent> pulledData) {
INotificationManager notificationManagerService = getINotificationManagerService();
if (notificationManagerService == null) {
return StatsManager.PULL_SKIP;
@@ -3601,7 +3764,7 @@
);
}
- int pullHealthHal(int atomTag, List<StatsEvent> pulledData) {
+ int pullHealthHalLocked(int atomTag, List<StatsEvent> pulledData) {
IHealth healthService = mHealthService.getLastService();
if (healthService == null) {
return StatsManager.PULL_SKIP;
@@ -3651,7 +3814,7 @@
);
}
- int pullSettingsStats(int atomTag, List<StatsEvent> pulledData) {
+ int pullSettingsStatsLocked(int atomTag, List<StatsEvent> pulledData) {
UserManager userManager = mContext.getSystemService(UserManager.class);
if (userManager == null) {
return StatsManager.PULL_SKIP;
@@ -3678,21 +3841,6 @@
return StatsManager.PULL_SUCCESS;
}
- private void registerDisplayWakeStats() {
- int tagId = FrameworkStatsLog.DISPLAY_WAKE_REASON;
- mStatsManager.setPullAtomCallback(
- tagId,
- null, // use default PullAtomMetadata values
- DIRECT_EXECUTOR,
- mStatsCallbackImpl
- );
- }
-
- int pullDisplayWakeStats(int atomTag, List<StatsEvent> pulledData) {
- //TODO: Denny, implement read/write DisplayWakeStats, b/154172964
- return 0;
- }
-
// Thermal event received from vendor thermal management subsystem
private static final class ThermalEventListener extends IThermalEventListener.Stub {
@Override
@@ -3749,11 +3897,13 @@
final SubInfo subInfo = new SubInfo(subId, sub.getCarrierId(), mcc, mnc,
subscriberId, sub.isOpportunistic());
Slog.i(TAG, "subId " + subId + " added into historical sub list");
- mHistoricalSubs.add(subInfo);
- // Since getting snapshot when pulling will also include data before boot,
- // query stats as baseline to prevent double count is needed.
- mNetworkStatsBaselines.addAll(getDataUsageBytesTransferSnapshotForSub(subInfo));
+ synchronized (mDataBytesTransferLock) {
+ mHistoricalSubs.add(subInfo);
+ // Since getting snapshot when pulling will also include data before boot,
+ // query stats as baseline to prevent double count is needed.
+ mNetworkStatsBaselines.addAll(getDataUsageBytesTransferSnapshotForSub(subInfo));
+ }
}
}
}
diff --git a/services/core/java/com/android/server/storage/StorageUserConnection.java b/services/core/java/com/android/server/storage/StorageUserConnection.java
index c18a6eb..94a2502 100644
--- a/services/core/java/com/android/server/storage/StorageUserConnection.java
+++ b/services/core/java/com/android/server/storage/StorageUserConnection.java
@@ -413,20 +413,18 @@
resetUserSessions();
}
};
- }
- Slog.i(TAG, "Binding to the ExternalStorageService for user " + mUserId);
- if (mContext.bindServiceAsUser(new Intent().setComponent(name), mServiceConnection,
- Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
- UserHandle.of(mUserId))) {
- Slog.i(TAG, "Bound to the ExternalStorageService for user " + mUserId);
- return mLatch;
- } else {
- synchronized (mLock) {
+ Slog.i(TAG, "Binding to the ExternalStorageService for user " + mUserId);
+ if (mContext.bindServiceAsUser(new Intent().setComponent(name), mServiceConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
+ UserHandle.of(mUserId))) {
+ Slog.i(TAG, "Bound to the ExternalStorageService for user " + mUserId);
+ return mLatch;
+ } else {
mIsConnecting = false;
+ throw new ExternalStorageServiceException(
+ "Failed to bind to the ExternalStorageService for user " + mUserId);
}
- throw new ExternalStorageServiceException(
- "Failed to bind to the ExternalStorageService for user " + mUserId);
}
}
}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 34998a0..b9240c7 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -898,11 +898,16 @@
/* ignore */
}
mSurfaceControl = surfaceControl;
- mService.mTransactionFactory.get().setLayer(mSurfaceControl,
- mService.mPolicy.getWindowLayerFromTypeLw(TYPE_MAGNIFICATION_OVERLAY)
- * WindowManagerService.TYPE_LAYER_MULTIPLIER)
- .setPosition(mSurfaceControl, 0, 0)
- .apply();
+
+ final SurfaceControl.Transaction t = mService.mTransactionFactory.get();
+ final int layer =
+ mService.mPolicy.getWindowLayerFromTypeLw(TYPE_MAGNIFICATION_OVERLAY) *
+ WindowManagerService.TYPE_LAYER_MULTIPLIER;
+ t.setLayer(mSurfaceControl, layer).setPosition(mSurfaceControl, 0, 0);
+ InputMonitor.setTrustedOverlayInputInfo(mSurfaceControl, t,
+ mDisplayContent.getDisplayId(), "Magnification Overlay");
+ t.apply();
+
mSurface.copyFrom(mSurfaceControl);
mAnimationController = new AnimationController(context,
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index f643fff..be2f9d4 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2842,7 +2842,8 @@
// their client may have activities.
// No longer have activities, so update LRU list and oom adj.
app.updateProcessInfo(true /* updateServiceConnectionActivities */,
- false /* activityChange */, true /* updateOomAdj */);
+ false /* activityChange */, true /* updateOomAdj */,
+ false /* addPendingTopUid */);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 2146f77..4bede4c 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -1682,7 +1682,8 @@
// happens to be sitting towards the end.
if (next.attachedToProcess()) {
next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
- true /* activityChange */, false /* updateOomAdj */);
+ true /* activityChange */, false /* updateOomAdj */,
+ false /* addPendingTopUid */);
} else if (!next.isProcessRunning()) {
// Since the start-process is asynchronous, if we already know the process of next
// activity isn't running, we can start the process earlier to save the time to wait
@@ -1839,7 +1840,8 @@
next.setState(RESUMED, "resumeTopActivityInnerLocked");
next.app.updateProcessInfo(false /* updateServiceConnectionActivities */,
- true /* activityChange */, true /* updateOomAdj */);
+ true /* activityChange */, true /* updateOomAdj */,
+ true /* addPendingTopUid */);
// Have the window manager re-evaluate the orientation of
// the screen based on the new activity order.
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 5f591b5..7c935d0 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4873,6 +4873,10 @@
return;
}
+ if (isInPictureInPictureMode(activity)) {
+ throw new IllegalStateException("Activity is already in PIP mode");
+ }
+
final boolean canEnterPictureInPicture = activity.checkEnterPictureInPictureState(
"requestPictureInPictureMode", /* beforeStopping */ false);
if (!canEnterPictureInPicture) {
diff --git a/services/core/java/com/android/server/wm/AlertWindowNotification.java b/services/core/java/com/android/server/wm/AlertWindowNotification.java
index 7b511ec..fde0369 100644
--- a/services/core/java/com/android/server/wm/AlertWindowNotification.java
+++ b/services/core/java/com/android/server/wm/AlertWindowNotification.java
@@ -18,6 +18,7 @@
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
+import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.content.Context.NOTIFICATION_SERVICE;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -139,7 +140,8 @@
Uri.fromParts("package", packageName, null));
intent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
// Calls into activity manager...
- return PendingIntent.getActivity(context, mRequestCode, intent, FLAG_CANCEL_CURRENT);
+ return PendingIntent.getActivity(context, mRequestCode, intent,
+ FLAG_CANCEL_CURRENT | FLAG_IMMUTABLE);
}
private void createNotificationChannel(Context context, String appName) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 05594c8..4e19a52 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3504,22 +3504,21 @@
* doesn't support IME/system decorations.
*
* @param target current IME target.
- * @return {@link WindowState} that can host IME.
+ * @return {@link InsetsControlTarget} that can host IME.
*/
- WindowState getImeHostOrFallback(WindowState target) {
+ InsetsControlTarget getImeHostOrFallback(WindowState target) {
if (target != null && target.getDisplayContent().canShowIme()) {
return target;
}
return getImeFallback();
}
- WindowState getImeFallback() {
-
+ InsetsControlTarget getImeFallback() {
// host is in non-default display that doesn't support system decor, default to
- // default display's StatusBar to control IME.
- // TODO: (b/148234093)find a better host OR control IME animation/visibility directly
- // because it won't work when statusbar isn't available.
- return mWmService.getDefaultDisplayContentLocked().getDisplayPolicy().getStatusBar();
+ // default display's StatusBar to control IME (when available), else let system control it.
+ WindowState statusBar =
+ mWmService.getDefaultDisplayContentLocked().getDisplayPolicy().getStatusBar();
+ return statusBar != null ? statusBar : mRemoteInsetsControlTarget;
}
boolean canShowIme() {
diff --git a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
index 2165b0e..c9cc944 100644
--- a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
+++ b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
@@ -66,6 +66,9 @@
t.setLayer(ctrl, zOrder);
t.setPosition(ctrl, 0, 0);
t.show(ctrl);
+ // Ensure we aren't considered as obscuring for Input purposes.
+ InputMonitor.setTrustedOverlayInputInfo(ctrl, t,
+ dc.getDisplayId(), "EmulatorDisplayOverlay");
mSurface.copyFrom(ctrl);
} catch (OutOfResourcesException e) {
}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index efcd61d..8734b5e 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -16,13 +16,17 @@
package com.android.server.wm;
+import static android.os.Process.myPid;
+import static android.os.Process.myUid;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
import static android.view.WindowManager.INPUT_CONSUMER_PIP;
import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
+import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
@@ -550,4 +554,26 @@
}
}
}
+
+ /**
+ * Helper function to generate an InputInfo with type SECURE_SYSTEM_OVERLAY. This input
+ * info will not have an input channel or be touchable, but is used to omit Surfaces
+ * from occlusion detection, so that System global overlays like the Watermark aren't
+ * counted by the InputDispatcher as occluding applications below.
+ */
+ static void setTrustedOverlayInputInfo(SurfaceControl sc, SurfaceControl.Transaction t,
+ int displayId, String name) {
+ InputWindowHandle inputWindowHandle = new InputWindowHandle(null, displayId);
+ inputWindowHandle.name = name;
+ inputWindowHandle.layoutParamsType = TYPE_SECURE_SYSTEM_OVERLAY;
+ inputWindowHandle.dispatchingTimeoutNanos = -1;
+ inputWindowHandle.visible = true;
+ inputWindowHandle.canReceiveKeys = false;
+ inputWindowHandle.hasFocus = false;
+ inputWindowHandle.ownerPid = myPid();
+ inputWindowHandle.ownerUid = myUid();
+ inputWindowHandle.inputFeatures = INPUT_FEATURE_NO_INPUT_CHANNEL;
+ inputWindowHandle.scaleFactor = 1;
+ t.setInputWindowInfo(sc, inputWindowHandle);
+ }
}
diff --git a/services/core/java/com/android/server/wm/StrictModeFlash.java b/services/core/java/com/android/server/wm/StrictModeFlash.java
index f537005..fa62daa 100644
--- a/services/core/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/core/java/com/android/server/wm/StrictModeFlash.java
@@ -54,6 +54,10 @@
t.setLayer(ctrl, WindowManagerService.TYPE_LAYER_MULTIPLIER * 101);
t.setPosition(ctrl, 0, 0);
t.show(ctrl);
+ // Ensure we aren't considered as obscuring for Input purposes.
+ InputMonitor.setTrustedOverlayInputInfo(ctrl, t, dc.getDisplayId(),
+ "StrictModeFlash");
+
mSurface.copyFrom(ctrl);
} catch (OutOfResourcesException e) {
}
diff --git a/services/core/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java
index 4e1b217..3d49ebe 100644
--- a/services/core/java/com/android/server/wm/Watermark.java
+++ b/services/core/java/com/android/server/wm/Watermark.java
@@ -29,6 +29,7 @@
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
+import android.view.InputWindowHandle;
import android.view.Surface;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
@@ -124,6 +125,8 @@
t.setLayer(ctrl, WindowManagerService.TYPE_LAYER_MULTIPLIER * 100)
.setPosition(ctrl, 0, 0)
.show(ctrl);
+ // Ensure we aren't considered as obscuring for Input purposes.
+ InputMonitor.setTrustedOverlayInputInfo(ctrl, t, dc.getDisplayId(), "Watermark");
mSurface.copyFrom(ctrl);
} catch (OutOfResourcesException e) {
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d1366bd..0590288 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5616,11 +5616,6 @@
mLatencyTracker.onActionStart(ACTION_ROTATE_SCREEN);
mExitAnimId = exitAnim;
mEnterAnimId = enterAnim;
- ScreenRotationAnimation screenRotationAnimation =
- displayContent.getRotationAnimation();
- if (screenRotationAnimation != null) {
- screenRotationAnimation.kill();
- }
displayContent.updateDisplayInfo();
final int originalRotation = overrideOriginalRotation != ROTATION_UNDEFINED
@@ -7628,8 +7623,12 @@
if (imeTarget == null) {
return;
}
- imeTarget = imeTarget.getImeControlTarget();
- imeTarget.getDisplayContent().getInsetsStateController().getImeSourceProvider()
+ imeTarget = imeTarget.getImeControlTarget().getWindow();
+ // If InsetsControlTarget doesn't have a window, its using remoteControlTarget which
+ // is controlled by default display
+ final DisplayContent dc = imeTarget != null
+ ? imeTarget.getDisplayContent() : getDefaultDisplayContentLocked();
+ dc.getInsetsStateController().getImeSourceProvider()
.scheduleShowImePostLayout(imeTarget);
}
}
@@ -7642,7 +7641,9 @@
// The target window no longer exists.
return;
}
- final DisplayContent dc = imeTarget.getImeControlTarget().getDisplayContent();
+ imeTarget = imeTarget.getImeControlTarget().getWindow();
+ final DisplayContent dc = imeTarget != null
+ ? imeTarget.getDisplayContent() : getDefaultDisplayContentLocked();
// If there was a pending IME show(), reset it as IME has been
// requested to be hidden.
dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout();
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 2ec6df5..29cf177 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -1007,8 +1007,11 @@
}
void updateProcessInfo(boolean updateServiceConnectionActivities, boolean activityChange,
- boolean updateOomAdj) {
+ boolean updateOomAdj, boolean addPendingTopUid) {
if (mListener == null) return;
+ if (addPendingTopUid) {
+ mAtm.mAmInternal.addPendingTopUid(mUid, mPid);
+ }
// Posting on handler so WM lock isn't held when we call into AM.
final Message m = PooledLambda.obtainMessage(WindowProcessListener::updateProcessInfo,
mListener, updateServiceConnectionActivities, activityChange, updateOomAdj);
@@ -1068,7 +1071,7 @@
}
// update ActivityManagerService.PendingStartActivityUids list.
if (topProcessState == ActivityManager.PROCESS_STATE_TOP) {
- mAtm.mAmInternal.updatePendingTopUid(mUid, true);
+ mAtm.mAmInternal.addPendingTopUid(mUid, mPid);
}
// Posting the message at the front of queue so WM lock isn't held when we call into AM,
// and the process state of starting activity can be updated quicker which will give it a
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 36232e1..fe3ee50 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5404,10 +5404,10 @@
* {@link android.view.inputmethod.InputMethodManager#showSoftInput(View, int)} is unknown,
* use {@link DisplayContent#getImeControlTarget()} instead.
*
- * @return {@link WindowState} of host that controls the IME.
+ * @return {@link InsetsControlTarget} of host that controls the IME.
* When window is doesn't have a parent, it is returned as-is.
*/
- WindowState getImeControlTarget() {
+ InsetsControlTarget getImeControlTarget() {
final DisplayContent dc = getDisplayContent();
final WindowState parentWindow = dc.getParentWindow();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index f1064d1..df55b3b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2616,6 +2616,8 @@
mSetupContentObserver = new SetupContentObserver(mHandler);
mUserManagerInternal.addUserRestrictionsListener(new RestrictionsListener(mContext));
+
+ loadOwners();
}
/**
@@ -2676,12 +2678,23 @@
}
}
+ /**
+ * Load information about device and profile owners of the device, populating mOwners and
+ * pushing owner info to other system services. This is called at a fairly early stage of
+ * system server initialiation (via DevicePolicyManagerService's ctor), so care should to
+ * be taken to not interact with system services that are initialiated after DPMS.
+ * onLockSettingsReady() is a safer place to do initialization work not critical during
+ * the first boot stage.
+ * Note this only loads the list of owners, and not their actual policy (DevicePolicyData).
+ * The policy is normally loaded lazily when it's first accessed. In several occasions
+ * the list of owners is necessary for providing callers with aggregated policies across
+ * multiple owners, hence the owner list is loaded as part of DPMS's construction here.
+ */
void loadOwners() {
synchronized (getLockObject()) {
mOwners.load();
setDeviceOwnershipSystemPropertyLocked();
findOwnerComponentIfNecessaryLocked();
- migrateUserRestrictionsIfNecessaryLocked();
// TODO PO may not have a class name either due to b/17652534. Address that too.
updateDeviceOwnerLocked();
@@ -4104,8 +4117,10 @@
}
private void onLockSettingsReady() {
+ synchronized (getLockObject()) {
+ migrateUserRestrictionsIfNecessaryLocked();
+ }
getUserData(UserHandle.USER_SYSTEM);
- loadOwners();
cleanUpOldUsers();
maybeSetDefaultProfileOwnerUserRestrictions();
handleStartUser(UserHandle.USER_SYSTEM);
diff --git a/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/SourceStampTestApk.apk b/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/SourceStampTestApk.apk
index 8056e0b..211e064 100644
--- a/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/SourceStampTestApk.apk
+++ b/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/SourceStampTestApk.apk
Binary files differ
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index 48e70e0..c44f127 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -57,6 +57,7 @@
private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
private int mPlaybackPhysicalAddress;
private boolean mWokenUp;
+ private boolean mStandby;
@Mock private IPowerManager mIPowerManagerMock;
@Mock private IThermalService mIThermalServiceMock;
@@ -77,6 +78,11 @@
}
@Override
+ void standby() {
+ mStandby = true;
+ }
+
+ @Override
boolean isControlEnabled() {
return true;
}
@@ -337,6 +343,52 @@
}
@Test
+ public void handleActiveSource_ActiveSource_None() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE;
+ mStandby = false;
+ HdmiCecMessage message = HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1,
+ mPlaybackPhysicalAddress);
+ assertThat(mHdmiCecLocalDevicePlayback.handleActiveSource(message)).isTrue();
+ mTestLooper.dispatchAll();
+ assertThat(mStandby).isFalse();
+ }
+
+ @Test
+ public void handleActiveSource_notActiveSource_None() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE;
+ mStandby = false;
+ HdmiCecMessage message = HdmiCecMessageBuilder.buildActiveSource(ADDR_TV, 0x0000);
+ assertThat(mHdmiCecLocalDevicePlayback.handleActiveSource(message)).isTrue();
+ mTestLooper.dispatchAll();
+ assertThat(mStandby).isFalse();
+ }
+
+ @Test
+ public void handleActiveSource_ActiveSource_StandbyNow() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW;
+ mStandby = false;
+ HdmiCecMessage message = HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1,
+ mPlaybackPhysicalAddress);
+ assertThat(mHdmiCecLocalDevicePlayback.handleActiveSource(message)).isTrue();
+ mTestLooper.dispatchAll();
+ assertThat(mStandby).isFalse();
+ }
+
+ @Test
+ public void handleActiveSource_notActiveSource_StandbyNow() {
+ mHdmiCecLocalDevicePlayback.mPowerStateChangeOnActiveSourceLost =
+ Constants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW;
+ mStandby = false;
+ HdmiCecMessage message = HdmiCecMessageBuilder.buildActiveSource(ADDR_TV, 0x0000);
+ assertThat(mHdmiCecLocalDevicePlayback.handleActiveSource(message)).isTrue();
+ mTestLooper.dispatchAll();
+ assertThat(mStandby).isTrue();
+ }
+
+ @Test
public void sendVolumeKeyEvent_up_volumeEnabled() {
mHdmiControlService.setHdmiCecVolumeControlEnabled(true);
mHdmiCecLocalDevicePlayback.sendVolumeKeyEvent(KeyEvent.KEYCODE_VOLUME_UP, true);
diff --git a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
index 53c9bb2..9ca84d3 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
@@ -121,7 +121,7 @@
private static final String INSTALLER_SHA256 =
"30F41A7CBF96EE736A54DD6DF759B50ED3CC126ABCEF694E167C324F5976C227";
private static final String SOURCE_STAMP_CERTIFICATE_HASH =
- "681B0E56A796350C08647352A4DB800CC44B2ADC8F4C72FA350BD05D4D50264D";
+ "C6E737809CEF2B08CC6694892215F82A5E8FBC3C2A0F6212770310B90622D2D9";
private static final String DUMMY_APP_TWO_CERTS_CERT_1 =
"C0369C2A1096632429DFA8433068AECEAD00BAC337CA92A175036D39CC9AFE94";
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index f205fde..399a00f0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -23,6 +23,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -57,6 +58,7 @@
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
import java.security.cert.CertificateException;
import java.util.ArrayList;
@@ -69,16 +71,20 @@
@RunWith(JUnit4.class)
public class AppsFilterTest {
- private static final int DUMMY_CALLING_UID = 10345;
- private static final int DUMMY_TARGET_UID = 10556;
- private static final int DUMMY_ACTOR_UID = 10656;
- private static final int DUMMY_OVERLAY_UID = 10756;
- private static final int DUMMY_ACTOR_TWO_UID = 10856;
+ private static final int DUMMY_CALLING_APPID = 10345;
+ private static final int DUMMY_TARGET_APPID = 10556;
+ private static final int DUMMY_ACTOR_APPID = 10656;
+ private static final int DUMMY_OVERLAY_APPID = 10756;
+ private static final int SYSTEM_USER = 0;
+ private static final int[] SINGLE_USER_ARRAY = {SYSTEM_USER};
@Mock
AppsFilter.FeatureConfig mFeatureConfigMock;
+ @Mock
+ AppsFilter.StateProvider mStateProvider;
private ArrayMap<String, PackageSetting> mExisting = new ArrayMap<>();
+ private Object mDummyLock = new Object();
private static ParsingPackage pkg(String packageName) {
return PackageImpl.forTesting(packageName)
@@ -170,15 +176,24 @@
mExisting = new ArrayMap<>();
MockitoAnnotations.initMocks(this);
+ doAnswer(invocation -> {
+ ((AppsFilter.StateProvider.CurrentStateCallback) invocation.getArgument(0))
+ .currentState(mExisting, SINGLE_USER_ARRAY);
+ return null;
+ }).when(mStateProvider)
+ .runWithState(any(AppsFilter.StateProvider.CurrentStateCallback.class));
+
when(mFeatureConfigMock.isGloballyEnabled()).thenReturn(true);
- when(mFeatureConfigMock.packageIsEnabled(any(AndroidPackage.class)))
- .thenReturn(true);
+ when(mFeatureConfigMock.packageIsEnabled(any(AndroidPackage.class))).thenAnswer(
+ (Answer<Boolean>) invocation ->
+ ((AndroidPackage)invocation.getArgument(SYSTEM_USER)).getTargetSdkVersion()
+ >= Build.VERSION_CODES.R);
}
@Test
public void testSystemReadyPropogates() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
appsFilter.onSystemReady();
verify(mFeatureConfigMock).onSystemReady();
}
@@ -186,22 +201,23 @@
@Test
public void testQueriesAction_FilterMatches() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
- pkg("com.some.package", new IntentFilter("TEST_ACTION")), DUMMY_TARGET_UID);
+ pkg("com.some.package", new IntentFilter("TEST_ACTION")), DUMMY_TARGET_APPID);
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_UID);
+ pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_APPID);
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testQueriesProtectedAction_FilterDoesNotMatch() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
final Signature frameworkSignature = Mockito.mock(Signature.class);
final PackageParser.SigningDetails frameworkSigningDetails =
new PackageParser.SigningDetails(new Signature[]{frameworkSignature}, 1);
@@ -211,164 +227,174 @@
b -> b.setSigningDetails(frameworkSigningDetails));
appsFilter.onSystemReady();
- final int activityUid = DUMMY_TARGET_UID;
+ final int activityUid = DUMMY_TARGET_APPID;
PackageSetting targetActivity = simulateAddPackage(appsFilter,
pkg("com.target.activity", new IntentFilter("TEST_ACTION")), activityUid);
- final int receiverUid = DUMMY_TARGET_UID + 1;
+ final int receiverUid = DUMMY_TARGET_APPID + 1;
PackageSetting targetReceiver = simulateAddPackage(appsFilter,
pkgWithReceiver("com.target.receiver", new IntentFilter("TEST_ACTION")),
receiverUid);
- final int callingUid = DUMMY_CALLING_UID;
+ final int callingUid = DUMMY_CALLING_APPID;
PackageSetting calling = simulateAddPackage(appsFilter,
pkg("com.calling.action", new Intent("TEST_ACTION")), callingUid);
- final int wildcardUid = DUMMY_CALLING_UID + 1;
+ final int wildcardUid = DUMMY_CALLING_APPID + 1;
PackageSetting callingWildCard = simulateAddPackage(appsFilter,
pkg("com.calling.wildcard", new Intent("*")), wildcardUid);
- assertFalse(appsFilter.shouldFilterApplication(callingUid, calling, targetActivity, 0));
- assertTrue(appsFilter.shouldFilterApplication(callingUid, calling, targetReceiver, 0));
+ assertFalse(appsFilter.shouldFilterApplication(callingUid, calling, targetActivity,
+ SYSTEM_USER));
+ assertTrue(appsFilter.shouldFilterApplication(callingUid, calling, targetReceiver,
+ SYSTEM_USER));
assertFalse(appsFilter.shouldFilterApplication(
- wildcardUid, callingWildCard, targetActivity, 0));
+ wildcardUid, callingWildCard, targetActivity, SYSTEM_USER));
assertTrue(appsFilter.shouldFilterApplication(
- wildcardUid, callingWildCard, targetReceiver, 0));
+ wildcardUid, callingWildCard, targetReceiver, SYSTEM_USER));
}
@Test
public void testQueriesProvider_FilterMatches() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
- pkgWithProvider("com.some.package", "com.some.authority"), DUMMY_TARGET_UID);
+ pkgWithProvider("com.some.package", "com.some.authority"), DUMMY_TARGET_APPID);
PackageSetting calling = simulateAddPackage(appsFilter,
pkgQueriesProvider("com.some.other.package", "com.some.authority"),
- DUMMY_CALLING_UID);
+ DUMMY_CALLING_APPID);
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testQueriesDifferentProvider_Filters() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
- pkgWithProvider("com.some.package", "com.some.authority"), DUMMY_TARGET_UID);
+ pkgWithProvider("com.some.package", "com.some.authority"), DUMMY_TARGET_APPID);
PackageSetting calling = simulateAddPackage(appsFilter,
pkgQueriesProvider("com.some.other.package", "com.some.other.authority"),
- DUMMY_CALLING_UID);
+ DUMMY_CALLING_APPID);
- assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testQueriesProviderWithSemiColon_FilterMatches() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
pkgWithProvider("com.some.package", "com.some.authority;com.some.other.authority"),
- DUMMY_TARGET_UID);
+ DUMMY_TARGET_APPID);
PackageSetting calling = simulateAddPackage(appsFilter,
pkgQueriesProvider("com.some.other.package", "com.some.authority"),
- DUMMY_CALLING_UID);
+ DUMMY_CALLING_APPID);
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testQueriesAction_NoMatchingAction_Filters() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
- pkg("com.some.package"), DUMMY_TARGET_UID);
+ pkg("com.some.package"), DUMMY_TARGET_APPID);
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_UID);
+ pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_APPID);
- assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testQueriesAction_NoMatchingActionFilterLowSdk_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
- pkg("com.some.package"), DUMMY_TARGET_UID);
- PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package",
- new Intent("TEST_ACTION"))
- .setTargetSdkVersion(Build.VERSION_CODES.P),
- DUMMY_CALLING_UID);
+ pkg("com.some.package"), DUMMY_TARGET_APPID);
+ ParsingPackage callingPkg = pkg("com.some.other.package",
+ new Intent("TEST_ACTION"))
+ .setTargetSdkVersion(Build.VERSION_CODES.P);
+ PackageSetting calling = simulateAddPackage(appsFilter, callingPkg,
+ DUMMY_CALLING_APPID);
- when(mFeatureConfigMock.packageIsEnabled(calling.pkg)).thenReturn(false);
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testNoQueries_Filters() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
- pkg("com.some.package"), DUMMY_TARGET_UID);
+ pkg("com.some.package"), DUMMY_TARGET_APPID);
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package"), DUMMY_CALLING_UID);
+ pkg("com.some.other.package"), DUMMY_CALLING_APPID);
- assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testForceQueryable_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
- pkg("com.some.package").setForceQueryable(true), DUMMY_TARGET_UID);
+ pkg("com.some.package").setForceQueryable(true), DUMMY_TARGET_APPID);
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package"), DUMMY_CALLING_UID);
+ pkg("com.some.other.package"), DUMMY_CALLING_APPID);
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testForceQueryableByDevice_SystemCaller_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{"com.some.package"}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{"com.some.package"},
+ false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
- pkg("com.some.package"), DUMMY_TARGET_UID,
+ pkg("com.some.package"), DUMMY_TARGET_APPID,
setting -> setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package"), DUMMY_CALLING_UID);
+ pkg("com.some.other.package"), DUMMY_CALLING_APPID);
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testSystemSignedTarget_DoesntFilter() throws CertificateException {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
appsFilter.onSystemReady();
final Signature frameworkSignature = Mockito.mock(Signature.class);
@@ -382,62 +408,67 @@
simulateAddPackage(appsFilter, pkg("android"), 1000,
b -> b.setSigningDetails(frameworkSigningDetails));
PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
- DUMMY_TARGET_UID,
+ DUMMY_TARGET_APPID,
b -> b.setSigningDetails(frameworkSigningDetails)
.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package"), DUMMY_CALLING_UID,
+ pkg("com.some.other.package"), DUMMY_CALLING_APPID,
b -> b.setSigningDetails(otherSigningDetails));
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testForceQueryableByDevice_NonSystemCaller_Filters() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{"com.some.package"}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{"com.some.package"},
+ false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
- pkg("com.some.package"), DUMMY_TARGET_UID);
+ pkg("com.some.package"), DUMMY_TARGET_APPID);
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package"), DUMMY_CALLING_UID);
+ pkg("com.some.other.package"), DUMMY_CALLING_APPID);
- assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testSystemQueryable_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{},
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{},
true /* system force queryable */, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
- pkg("com.some.package"), DUMMY_TARGET_UID,
+ pkg("com.some.package"), DUMMY_TARGET_APPID,
setting -> setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package"), DUMMY_CALLING_UID);
+ pkg("com.some.other.package"), DUMMY_CALLING_APPID);
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testQueriesPackage_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
- pkg("com.some.package"), DUMMY_TARGET_UID);
+ pkg("com.some.package"), DUMMY_TARGET_APPID);
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package", "com.some.package"), DUMMY_CALLING_UID);
+ pkg("com.some.other.package", "com.some.package"), DUMMY_CALLING_APPID);
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
@@ -445,63 +476,67 @@
when(mFeatureConfigMock.packageIsEnabled(any(AndroidPackage.class)))
.thenReturn(false);
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(
- appsFilter, pkg("com.some.package"), DUMMY_TARGET_UID);
+ appsFilter, pkg("com.some.package"), DUMMY_TARGET_APPID);
PackageSetting calling = simulateAddPackage(
- appsFilter, pkg("com.some.other.package"), DUMMY_CALLING_UID);
+ appsFilter, pkg("com.some.other.package"), DUMMY_CALLING_APPID);
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testSystemUid_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
- pkg("com.some.package"), DUMMY_TARGET_UID);
+ pkg("com.some.package"), DUMMY_TARGET_APPID);
- assertFalse(appsFilter.shouldFilterApplication(0, null, target, 0));
+ assertFalse(appsFilter.shouldFilterApplication(SYSTEM_USER, null, target, SYSTEM_USER));
assertFalse(appsFilter.shouldFilterApplication(Process.FIRST_APPLICATION_UID - 1,
- null, target, 0));
+ null, target, SYSTEM_USER));
}
@Test
public void testNonSystemUid_NoCallingSetting_Filters() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
- pkg("com.some.package"), DUMMY_TARGET_UID);
+ pkg("com.some.package"), DUMMY_TARGET_APPID);
- assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, null, target, 0));
+ assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, null, target,
+ SYSTEM_USER));
}
@Test
public void testNoTargetPackage_filters() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = new PackageSettingBuilder()
+ .setAppId(DUMMY_TARGET_APPID)
.setName("com.some.package")
.setCodePath("/")
.setResourcePath("/")
.setPVersionCode(1L)
.build();
PackageSetting calling = simulateAddPackage(appsFilter,
- pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_UID);
+ pkg("com.some.other.package", new Intent("TEST_ACTION")), DUMMY_CALLING_APPID);
- assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
@@ -516,7 +551,11 @@
.setOverlayTargetName("overlayableName");
ParsingPackage actor = pkg("com.some.package.actor");
- final AppsFilter appsFilter = new AppsFilter(mFeatureConfigMock, new String[]{}, false,
+ final AppsFilter appsFilter = new AppsFilter(
+ mStateProvider,
+ mFeatureConfigMock,
+ new String[]{},
+ false,
new OverlayReferenceMapper.Provider() {
@Nullable
@Override
@@ -544,31 +583,34 @@
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
- PackageSetting targetSetting = simulateAddPackage(appsFilter, target, DUMMY_TARGET_UID);
- PackageSetting overlaySetting = simulateAddPackage(appsFilter, overlay, DUMMY_OVERLAY_UID);
- PackageSetting actorSetting = simulateAddPackage(appsFilter, actor, DUMMY_ACTOR_UID);
+ PackageSetting targetSetting = simulateAddPackage(appsFilter, target, DUMMY_TARGET_APPID);
+ PackageSetting overlaySetting =
+ simulateAddPackage(appsFilter, overlay, DUMMY_OVERLAY_APPID);
+ PackageSetting actorSetting = simulateAddPackage(appsFilter, actor, DUMMY_ACTOR_APPID);
// Actor can see both target and overlay
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_UID, actorSetting,
- targetSetting, 0));
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_UID, actorSetting,
- overlaySetting, 0));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_APPID, actorSetting,
+ targetSetting, SYSTEM_USER));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_APPID, actorSetting,
+ overlaySetting, SYSTEM_USER));
// But target/overlay can't see each other
- assertTrue(appsFilter.shouldFilterApplication(DUMMY_TARGET_UID, targetSetting,
- overlaySetting, 0));
- assertTrue(appsFilter.shouldFilterApplication(DUMMY_OVERLAY_UID, overlaySetting,
- targetSetting, 0));
+ assertTrue(appsFilter.shouldFilterApplication(DUMMY_TARGET_APPID, targetSetting,
+ overlaySetting, SYSTEM_USER));
+ assertTrue(appsFilter.shouldFilterApplication(DUMMY_OVERLAY_APPID, overlaySetting,
+ targetSetting, SYSTEM_USER));
// And can't see the actor
- assertTrue(appsFilter.shouldFilterApplication(DUMMY_TARGET_UID, targetSetting,
- actorSetting, 0));
- assertTrue(appsFilter.shouldFilterApplication(DUMMY_OVERLAY_UID, overlaySetting,
- actorSetting, 0));
+ assertTrue(appsFilter.shouldFilterApplication(DUMMY_TARGET_APPID, targetSetting,
+ actorSetting, SYSTEM_USER));
+ assertTrue(appsFilter.shouldFilterApplication(DUMMY_OVERLAY_APPID, overlaySetting,
+ actorSetting, SYSTEM_USER));
}
@Test
public void testActsOnTargetOfOverlayThroughSharedUser() throws Exception {
+// Debug.waitForDebugger();
+
final String actorName = "overlay://test/actorName";
ParsingPackage target = pkg("com.some.package.target")
@@ -580,7 +622,11 @@
ParsingPackage actorOne = pkg("com.some.package.actor.one");
ParsingPackage actorTwo = pkg("com.some.package.actor.two");
- final AppsFilter appsFilter = new AppsFilter(mFeatureConfigMock, new String[]{}, false,
+ final AppsFilter appsFilter = new AppsFilter(
+ mStateProvider,
+ mFeatureConfigMock,
+ new String[]{},
+ false,
new OverlayReferenceMapper.Provider() {
@Nullable
@Override
@@ -609,108 +655,114 @@
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
- PackageSetting targetSetting = simulateAddPackage(appsFilter, target, DUMMY_TARGET_UID);
- PackageSetting overlaySetting = simulateAddPackage(appsFilter, overlay, DUMMY_OVERLAY_UID);
- PackageSetting actorOneSetting = simulateAddPackage(appsFilter, actorOne, DUMMY_ACTOR_UID);
- PackageSetting actorTwoSetting = simulateAddPackage(appsFilter, actorTwo,
- DUMMY_ACTOR_TWO_UID);
-
+ PackageSetting targetSetting = simulateAddPackage(appsFilter, target, DUMMY_TARGET_APPID);
SharedUserSetting actorSharedSetting = new SharedUserSetting("actorSharedUser",
- actorOneSetting.pkgFlags, actorOneSetting.pkgPrivateFlags);
- actorSharedSetting.addPackage(actorOneSetting);
- actorSharedSetting.addPackage(actorTwoSetting);
+ targetSetting.pkgFlags, targetSetting.pkgPrivateFlags);
+ PackageSetting overlaySetting =
+ simulateAddPackage(appsFilter, overlay, DUMMY_OVERLAY_APPID);
+ simulateAddPackage(appsFilter, actorOne, DUMMY_ACTOR_APPID,
+ null /*settingBuilder*/, actorSharedSetting);
+ simulateAddPackage(appsFilter, actorTwo, DUMMY_ACTOR_APPID,
+ null /*settingBuilder*/, actorSharedSetting);
+
// actorTwo can see both target and overlay
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_TWO_UID, actorSharedSetting,
- targetSetting, 0));
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_TWO_UID, actorSharedSetting,
- overlaySetting, 0));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_APPID, actorSharedSetting,
+ targetSetting, SYSTEM_USER));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_ACTOR_APPID, actorSharedSetting,
+ overlaySetting, SYSTEM_USER));
}
@Test
public void testInitiatingApp_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
- DUMMY_TARGET_UID);
+ DUMMY_TARGET_APPID);
PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.some.other.package"),
- DUMMY_CALLING_UID, withInstallSource(target.name, null, null, false));
+ DUMMY_CALLING_APPID, withInstallSource(target.name, null, null, false));
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testUninstalledInitiatingApp_Filters() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
- DUMMY_TARGET_UID);
+ DUMMY_TARGET_APPID);
PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.some.other.package"),
- DUMMY_CALLING_UID, withInstallSource(target.name, null, null, true));
+ DUMMY_CALLING_APPID, withInstallSource(target.name, null, null, true));
- assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testOriginatingApp_Filters() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
- DUMMY_TARGET_UID);
+ DUMMY_TARGET_APPID);
PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.some.other.package"),
- DUMMY_CALLING_UID, withInstallSource(null, target.name, null, false));
+ DUMMY_CALLING_APPID, withInstallSource(null, target.name, null, false));
- assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testInstallingApp_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
- DUMMY_TARGET_UID);
+ DUMMY_TARGET_APPID);
PackageSetting calling = simulateAddPackage(appsFilter, pkg("com.some.other.package"),
- DUMMY_CALLING_UID, withInstallSource(null, null, target.name, false));
+ DUMMY_CALLING_APPID, withInstallSource(null, null, target.name, false));
- assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, calling, target, 0));
+ assertFalse(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
}
@Test
public void testInstrumentation_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
- DUMMY_TARGET_UID);
+ DUMMY_TARGET_APPID);
PackageSetting instrumentation = simulateAddPackage(appsFilter,
pkgWithInstrumentation("com.some.other.package", "com.some.package"),
- DUMMY_CALLING_UID);
+ DUMMY_CALLING_APPID);
assertFalse(
- appsFilter.shouldFilterApplication(DUMMY_CALLING_UID, instrumentation, target, 0));
+ appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, instrumentation, target,
+ SYSTEM_USER));
assertFalse(
- appsFilter.shouldFilterApplication(DUMMY_TARGET_UID, target, instrumentation, 0));
+ appsFilter.shouldFilterApplication(DUMMY_TARGET_APPID, target, instrumentation,
+ SYSTEM_USER));
}
@Test
public void testWhoCanSee() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -728,21 +780,25 @@
queriesProviderAppId);
final int[] systemFilter =
- appsFilter.getVisibilityWhitelist(system, new int[]{0}, mExisting).get(0);
+ appsFilter.getVisibilityWhitelist(system, SINGLE_USER_ARRAY, mExisting)
+ .get(SYSTEM_USER);
assertThat(toList(systemFilter), empty());
final int[] seesNothingFilter =
- appsFilter.getVisibilityWhitelist(seesNothing, new int[]{0}, mExisting).get(0);
+ appsFilter.getVisibilityWhitelist(seesNothing, SINGLE_USER_ARRAY, mExisting)
+ .get(SYSTEM_USER);
assertThat(toList(seesNothingFilter),
contains(seesNothingAppId));
final int[] hasProviderFilter =
- appsFilter.getVisibilityWhitelist(hasProvider, new int[]{0}, mExisting).get(0);
+ appsFilter.getVisibilityWhitelist(hasProvider, SINGLE_USER_ARRAY, mExisting)
+ .get(SYSTEM_USER);
assertThat(toList(hasProviderFilter),
contains(hasProviderAppId, queriesProviderAppId));
int[] queriesProviderFilter =
- appsFilter.getVisibilityWhitelist(queriesProvider, new int[]{0}, mExisting).get(0);
+ appsFilter.getVisibilityWhitelist(queriesProvider, SINGLE_USER_ARRAY, mExisting)
+ .get(SYSTEM_USER);
assertThat(toList(queriesProviderFilter),
contains(queriesProviderAppId));
@@ -751,7 +807,8 @@
// ensure implicit access is included in the filter
queriesProviderFilter =
- appsFilter.getVisibilityWhitelist(queriesProvider, new int[]{0}, mExisting).get(0);
+ appsFilter.getVisibilityWhitelist(queriesProvider, SINGLE_USER_ARRAY, mExisting)
+ .get(SYSTEM_USER);
assertThat(toList(queriesProviderFilter),
contains(hasProviderAppId, queriesProviderAppId));
}
@@ -779,11 +836,17 @@
private PackageSetting simulateAddPackage(AppsFilter filter,
ParsingPackage newPkgBuilder, int appId) {
- return simulateAddPackage(filter, newPkgBuilder, appId, null);
+ return simulateAddPackage(filter, newPkgBuilder, appId, null /*settingBuilder*/);
}
private PackageSetting simulateAddPackage(AppsFilter filter,
ParsingPackage newPkgBuilder, int appId, @Nullable WithSettingBuilder action) {
+ return simulateAddPackage(filter, newPkgBuilder, appId, action, null /*sharedUserSetting*/);
+ }
+
+ private PackageSetting simulateAddPackage(AppsFilter filter,
+ ParsingPackage newPkgBuilder, int appId, @Nullable WithSettingBuilder action,
+ @Nullable SharedUserSetting sharedUserSetting) {
AndroidPackage newPkg = ((ParsedPackage) newPkgBuilder.hideAsParsed()).hideAsFinal();
final PackageSettingBuilder settingBuilder = new PackageSettingBuilder()
@@ -795,8 +858,12 @@
.setPVersionCode(1L);
final PackageSetting setting =
(action == null ? settingBuilder : action.withBuilder(settingBuilder)).build();
- filter.addPackage(setting, mExisting);
mExisting.put(newPkg.getPackageName(), setting);
+ if (sharedUserSetting != null) {
+ sharedUserSetting.addPackage(setting);
+ setting.sharedUser = sharedUserSetting;
+ }
+ filter.addPackage(setting);
return setting;
}
@@ -809,4 +876,3 @@
return setting -> setting.setInstallSource(installSource);
}
}
-
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
index c55df51..87979fb 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
@@ -366,9 +366,75 @@
for (PackageInfo p : packageInfos) {
actualPackages.add(p.packageName);
}
+
+ // Add auto-generated RRO package to expectedPackages since they are not (supposed to be)
+ // in the whitelist but they should be installed.
+ for (PackageInfo p : packageInfos) {
+ if (p.isOverlayPackage()
+ && UserSystemPackageInstaller.hasAutoGeneratedRROSuffix(p.packageName)
+ && expectedPackages.contains(p.overlayTarget)) {
+ expectedPackages.add(p.packageName);
+ }
+ }
checkPackageDifferences(expectedPackages, actualPackages);
}
+ @Test
+ public void testAutoGeneratedRROMatchesSuffix() {
+ final List<PackageInfo> packageInfos = mContext.getPackageManager()
+ .getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
+
+ Log.v(TAG, "Found total packages: " + packageInfos.size());
+
+ for (PackageInfo p : packageInfos) {
+ if (p.packageName.contains(".auto_generated_rro_")) {
+ assertTrue("Auto-generated RRO package name does not match the suffix: "
+ + p.packageName,
+ UserSystemPackageInstaller.hasAutoGeneratedRROSuffix(p.packageName));
+ }
+ }
+ }
+
+ /**
+ * Test that overlay package not in whitelist should be installed for all user at Explicit mode.
+ */
+ @Test
+ public void testInstallOverlayPackagesExplicitMode() {
+ setUserTypePackageWhitelistMode(USER_TYPE_PACKAGE_WHITELIST_MODE_ENFORCE);
+
+ final String[] userTypes = new String[]{"type"};
+ final long maskOfType = 0b0001L;
+
+ final String packageName1 = "whitelistedPkg";
+ final String packageName2 = "nonWhitelistedPkg";
+ final String overlayName1 = String.format("%s.auto_generated_rro_product__", packageName1);
+ final String overlayName2 = String.format("%s.auto_generated_rro_product__", packageName2);
+
+ final AndroidPackage overlayPackage1 = ((ParsedPackage) PackageImpl.forTesting(overlayName1)
+ .setOverlay(true)
+ .setOverlayTarget(packageName1)
+ .hideAsParsed())
+ .hideAsFinal();
+
+ final AndroidPackage overlayPackage2 = ((ParsedPackage) PackageImpl.forTesting(overlayName2)
+ .setOverlay(true)
+ .setOverlayTarget(packageName2)
+ .hideAsParsed())
+ .hideAsFinal();
+
+ final ArrayMap<String, Long> userTypeWhitelist = new ArrayMap<>();
+ userTypeWhitelist.put(packageName1, maskOfType);
+
+ final Set<String> userWhitelist = new ArraySet<>();
+ userWhitelist.add(packageName1);
+
+ boolean implicit = false;
+ assertTrue("Overlay for package1 should be installed", UserSystemPackageInstaller
+ .shouldInstallPackage(overlayPackage1, userTypeWhitelist, userWhitelist, implicit));
+ assertFalse("Overlay for package2 should not be installed", UserSystemPackageInstaller
+ .shouldInstallPackage(overlayPackage2, userTypeWhitelist, userWhitelist, implicit));
+ }
+
/** Asserts that actual is a subset of expected. */
private void checkPackageDifferences(Set<String> expected, Set<String> actual) {
final Set<String> uniqueToExpected = new ArraySet<>(expected);
diff --git a/services/tests/servicestests/src/com/android/server/power/PreRebootLoggerTest.java b/services/tests/servicestests/src/com/android/server/power/PreRebootLoggerTest.java
index a138234..45574fc 100644
--- a/services/tests/servicestests/src/com/android/server/power/PreRebootLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PreRebootLoggerTest.java
@@ -23,6 +23,9 @@
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageInstaller.SessionInfo;
+import android.content.pm.PackageManager;
import android.provider.Settings;
import android.test.mock.MockContentResolver;
@@ -36,12 +39,15 @@
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import java.io.File;
+import java.util.List;
/**
* Tests for {@link PreRebootLogger}
@@ -49,7 +55,11 @@
@SmallTest
@RunWith(AndroidJUnit4.class)
public class PreRebootLoggerTest {
+ @Rule public final MockitoRule mocks = MockitoJUnit.rule();
@Mock Context mContext;
+ @Mock PackageManager mPackageManager;
+ @Mock PackageInstaller mPackageInstaller;
+ @Mock List<SessionInfo> mSessions;
private MockContentResolver mContentResolver;
private File mDumpDir;
@@ -64,29 +74,53 @@
}
@Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
+ public void enableAdbConfig() {
mContentResolver = new MockContentResolver(getInstrumentation().getTargetContext());
when(mContext.getContentResolver()).thenReturn(mContentResolver);
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+ Settings.Global.putInt(mContentResolver, Settings.Global.ADB_ENABLED, 1);
+ }
+ @Before
+ public void prepareActiveStagedSessions() {
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mPackageManager.getPackageInstaller()).thenReturn(mPackageInstaller);
+ when(mPackageInstaller.getActiveStagedSessions()).thenReturn(mSessions);
+ when(mSessions.isEmpty()).thenReturn(false);
+ }
+
+ @Before
+ public void setupDumpDir() {
mDumpDir = Files.createTempDir();
- mDumpDir.mkdir();
mDumpDir.deleteOnExit();
}
@Test
- public void log_adbEnabled_dumpsInformationProperly() {
- Settings.Global.putInt(mContentResolver, Settings.Global.ADB_ENABLED, 1);
-
+ public void log_dumpsInformationProperly() {
PreRebootLogger.log(mContext, mDumpDir);
assertThat(mDumpDir.list()).asList().containsExactly("system", "package", "rollback");
}
@Test
+ public void dump_exceedTimeout_wontBlockCurrentThread() {
+ PreRebootLogger.dump(mDumpDir, 1 /* maxWaitTime */);
+
+ assertThat(mDumpDir.listFiles()).asList().containsNoneOf("system", "package", "rollback");
+ }
+
+ @Test
+ public void log_noActiveStagedSession_wipesDumpedInformation() {
+ PreRebootLogger.log(mContext, mDumpDir);
+ when(mSessions.isEmpty()).thenReturn(true);
+
+ PreRebootLogger.log(mContext, mDumpDir);
+
+ assertThat(mDumpDir.listFiles()).isEmpty();
+ }
+
+ @Test
public void log_adbDisabled_wipesDumpedInformation() {
- Settings.Global.putInt(mContentResolver, Settings.Global.ADB_ENABLED, 1);
PreRebootLogger.log(mContext, mDumpDir);
Settings.Global.putInt(mContentResolver, Settings.Global.ADB_ENABLED, 0);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
index 80b474f..6991c18 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationHistoryDatabaseTest.java
@@ -360,13 +360,12 @@
mDataBase.new WriteBufferRunnable();
mDataBase.mBuffer = nh;
- wbr.currentTime = 5;
- wbr.latestNotificationsFile = mock(AtomicFile.class);
+ AtomicFile af = mock(AtomicFile.class);
File file = mock(File.class);
when(file.getName()).thenReturn("5");
- when(wbr.latestNotificationsFile.getBaseFile()).thenReturn(file);
+ when(af.getBaseFile()).thenReturn(file);
- wbr.run();
+ wbr.run(5, af);
assertThat(mDataBase.mHistoryFiles.size()).isEqualTo(1);
assertThat(mDataBase.mBuffer).isNotEqualTo(nh);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index de9b77c..ae22b2b 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -5455,25 +5455,49 @@
}
@Test
- public void testCancelNotificationsFromListener_ignoresBubbles() throws Exception {
- final NotificationRecord nrNormal = generateNotificationRecord(mTestNotificationChannel);
- final NotificationRecord nrBubble = generateNotificationRecord(mTestNotificationChannel);
- nrBubble.getSbn().getNotification().flags |= FLAG_BUBBLE;
+ public void testCancelNotificationsFromListener_cancelsNonBubble() throws Exception {
+ // Add non-bubble notif
+ final NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
+ mService.addNotification(nr);
- mService.addNotification(nrNormal);
- mService.addNotification(nrBubble);
-
- String[] keys = {nrNormal.getSbn().getKey(), nrBubble.getSbn().getKey()};
+ // Cancel via listener
+ String[] keys = {nr.getSbn().getKey()};
mService.getBinderService().cancelNotificationsFromListener(null, keys);
waitForIdle();
+ // Notif not active anymore
+ StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
+ assertEquals(0, notifs.length);
+ assertEquals(0, mService.getNotificationRecordCount());
+ // Cancel event is logged
+ assertEquals(1, mNotificationRecordLogger.numCalls());
+ assertEquals(NotificationRecordLogger.NotificationCancelledEvent
+ .NOTIFICATION_CANCEL_LISTENER_CANCEL, mNotificationRecordLogger.event(0));
+ }
+
+ @Test
+ public void testCancelNotificationsFromListener_suppressesBubble() throws Exception {
+ // Add bubble notif
+ setUpPrefsForBubbles(PKG, mUid,
+ true /* global */,
+ BUBBLE_PREFERENCE_ALL /* app */,
+ true /* channel */);
+ NotificationRecord nr = generateMessageBubbleNotifRecord(mTestNotificationChannel, "tag");
+
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, nr.getSbn().getTag(),
+ nr.getSbn().getId(), nr.getSbn().getNotification(), nr.getSbn().getUserId());
+ waitForIdle();
+
+ // Cancel via listener
+ String[] keys = {nr.getSbn().getKey()};
+ mService.getBinderService().cancelNotificationsFromListener(null, keys);
+ waitForIdle();
+
+ // Bubble notif active and suppressed
StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
assertEquals(1, notifs.length);
assertEquals(1, mService.getNotificationRecordCount());
-
- assertEquals(1, mNotificationRecordLogger.numCalls());
- assertEquals(NotificationRecordLogger.NotificationCancelledEvent
- .NOTIFICATION_CANCEL_LISTENER_CANCEL, mNotificationRecordLogger.event(0));
+ assertTrue(notifs[0].getNotification().getBubbleMetadata().isNotificationSuppressed());
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/WrappedSysUiStatsEvent.java b/services/tests/uiservicestests/src/com/android/server/notification/WrappedSysUiStatsEvent.java
index f4f64d7..89adc72 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/WrappedSysUiStatsEvent.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/WrappedSysUiStatsEvent.java
@@ -88,11 +88,21 @@
return index < mValues.size() ? mValues.get(index) : null;
}
- /** useful to make assertTrue() statemetns more readable. */
+ /** useful to make assertTrue() statements more readable. */
public boolean getBoolean(int index) {
return (Boolean) mValues.get(index);
}
+ /** useful to make assertTrue() statements more readable. */
+ public int getInt(int index) {
+ return (Integer) mValues.get(index);
+ }
+
+ /** useful to make assertTrue() statements more readable. */
+ public String getString(int index) {
+ return (String) mValues.get(index);
+ }
+
private void addValue(Object value) {
mLastIndex = mValues.size();
mValues.add(value);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
index f7b435e..013a994 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java
@@ -101,11 +101,39 @@
Policy expectedPolicy = new Policy(priorityCategories, priorityCallSenders,
priorityMessageSenders, suppressedVisualEffects, 0, priorityConversationsSenders);
-
assertEquals(expectedPolicy, config.toNotificationPolicy(zenPolicy));
}
@Test
+ public void testZenConfigToZenPolicy() {
+ ZenPolicy expected = new ZenPolicy.Builder()
+ .allowAlarms(true)
+ .allowReminders(true)
+ .allowEvents(true)
+ .showLights(false)
+ .showBadges(false)
+ .showInAmbientDisplay(false)
+ .build();
+
+ ZenModeConfig config = getMutedAllConfig();
+ config.allowAlarms = true;
+ config.allowReminders = true;
+ config.allowEvents = true;
+ config.suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_BADGE;
+ config.suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_LIGHTS;
+ config.suppressedVisualEffects |= Policy.SUPPRESSED_EFFECT_AMBIENT;
+ ZenPolicy actual = config.toZenPolicy();
+
+ assertEquals(expected.getVisualEffectBadge(), actual.getVisualEffectBadge());
+ assertEquals(expected.getPriorityCategoryAlarms(), actual.getPriorityCategoryAlarms());
+ assertEquals(expected.getPriorityCategoryReminders(),
+ actual.getPriorityCategoryReminders());
+ assertEquals(expected.getPriorityCategoryEvents(), actual.getPriorityCategoryEvents());
+ assertEquals(expected.getVisualEffectLights(), actual.getVisualEffectLights());
+ assertEquals(expected.getVisualEffectAmbient(), actual.getVisualEffectAmbient());
+ }
+
+ @Test
public void testPriorityOnlyMutingAll() {
ZenModeConfig config = getMutedAllConfig();
assertTrue(ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(config));
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 108af89..3c7206f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -27,16 +27,25 @@
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM;
import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
-import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS;
import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_STARRED;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
+import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+
+import static com.android.internal.util.FrameworkStatsLog.ANNOTATION_ID_IS_UID;
+import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
+import static com.android.os.AtomsProto.DNDModeProto.CHANNELS_BYPASSING_FIELD_NUMBER;
+import static com.android.os.AtomsProto.DNDModeProto.ENABLED_FIELD_NUMBER;
+import static com.android.os.AtomsProto.DNDModeProto.ID_FIELD_NUMBER;
+import static com.android.os.AtomsProto.DNDModeProto.UID_FIELD_NUMBER;
+import static com.android.os.AtomsProto.DNDModeProto.ZEN_MODE_FIELD_NUMBER;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.TestCase.assertTrue;
+import static junit.framework.TestCase.fail;
import static org.junit.Assert.assertNotEquals;
import static org.mockito.ArgumentMatchers.any;
@@ -70,10 +79,12 @@
import android.media.AudioSystem;
import android.media.VolumePolicy;
import android.net.Uri;
+import android.os.Process;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.notification.Condition;
+import android.service.notification.DNDModeProto;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.ScheduleInfo;
import android.service.notification.ZenPolicy;
@@ -82,6 +93,7 @@
import android.testing.TestableLooper;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.StatsEvent;
import android.util.Xml;
import com.android.internal.R;
@@ -106,6 +118,9 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Objects;
@SmallTest
@@ -115,6 +130,7 @@
private static final String EVENTS_DEFAULT_RULE_ID = "EVENTS_DEFAULT_RULE";
private static final String SCHEDULE_DEFAULT_RULE_ID = "EVERY_NIGHT_DEFAULT_RULE";
+ private static final int ZEN_MODE_FOR_TESTING = 99;
ConditionProviders mConditionProviders;
@Mock NotificationManager mNotificationManager;
@@ -124,6 +140,7 @@
private Context mContext;
private ContentResolver mContentResolver;
@Mock AppOpsManager mAppOps;
+ private WrappedSysUiStatsEvent.WrappedBuilderFactory mStatsEventBuilderFactory;
@Before
public void setUp() {
@@ -140,6 +157,7 @@
Log.d("ZenModeHelperTest", "Couldn't mock default zen mode config xml file err=" +
e.toString());
}
+ mStatsEventBuilderFactory = new WrappedSysUiStatsEvent.WrappedBuilderFactory();
when(mContext.getSystemService(AppOpsManager.class)).thenReturn(mAppOps);
when(mContext.getSystemService(NotificationManager.class)).thenReturn(mNotificationManager);
@@ -147,7 +165,7 @@
AppGlobals.getPackageManager());
mConditionProviders.addSystemProvider(new CountdownConditionProvider());
mZenModeHelperSpy = spy(new ZenModeHelper(mContext, mTestableLooper.getLooper(),
- mConditionProviders));
+ mConditionProviders, mStatsEventBuilderFactory));
}
private XmlResourceParser getDefaultConfigParser() throws IOException, XmlPullParserException {
@@ -212,6 +230,10 @@
}
private ArrayMap<String, ZenModeConfig.ZenRule> getCustomAutomaticRules() {
+ return getCustomAutomaticRules(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+ }
+
+ private ArrayMap<String, ZenModeConfig.ZenRule> getCustomAutomaticRules(int zenMode) {
ArrayMap<String, ZenModeConfig.ZenRule> automaticRules = new ArrayMap<>();
ZenModeConfig.ZenRule customRule = new ZenModeConfig.ZenRule();
final ScheduleInfo customRuleInfo = new ScheduleInfo();
@@ -219,10 +241,10 @@
customRule.creationTime = 0;
customRule.id = "customRule";
customRule.name = "Custom Rule";
- customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ customRule.zenMode = zenMode;
customRule.conditionId = ZenModeConfig.toScheduleConditionId(customRuleInfo);
customRule.configurationActivity =
- new ComponentName("android", "ScheduleConditionProvider");
+ new ComponentName("not.android", "ScheduleConditionProvider");
customRule.pkg = customRule.configurationActivity.getPackageName();
automaticRules.put("customRule", customRule);
return automaticRules;
@@ -244,7 +266,7 @@
@Test
public void testZenOn_NotificationApplied() {
- mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
// The most permissive policy
mZenModeHelperSpy.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS |
PRIORITY_CATEGORY_MEDIA | PRIORITY_CATEGORY_MESSAGES
@@ -267,7 +289,7 @@
@Test
public void testZenOn_StarredCallers_CallTypesBlocked() {
- mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
// The most permissive policy
mZenModeHelperSpy.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS |
PRIORITY_CATEGORY_MEDIA | PRIORITY_CATEGORY_MESSAGES
@@ -287,7 +309,7 @@
@Test
public void testZenOn_AllCallers_CallTypesAllowed() {
- mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
// The most permissive policy
mZenModeHelperSpy.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS |
PRIORITY_CATEGORY_MEDIA | PRIORITY_CATEGORY_MESSAGES
@@ -307,7 +329,7 @@
@Test
public void testZenOn_AllowAlarmsMedia_NoAlarmMediaMuteApplied() {
- mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS |
PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0, 0);
@@ -320,7 +342,7 @@
@Test
public void testZenOn_DisallowAlarmsMedia_AlarmMediaMuteApplied() {
- mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
mZenModeHelperSpy.applyRestrictions();
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, true,
@@ -406,7 +428,7 @@
public void testZenAllCannotBypass() {
// Only audio attributes with SUPPRESIBLE_NEVER can bypass
// with special case USAGE_ASSISTANCE_SONIFICATION
- mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
mZenModeHelperSpy.applyRestrictions();
@@ -428,7 +450,7 @@
@Test
public void testApplyRestrictions_whitelist_priorityOnlyMode() {
mZenModeHelperSpy.setPriorityOnlyDndExemptPackages(new String[] {PKG_O});
- mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
mZenModeHelperSpy.applyRestrictions();
@@ -479,7 +501,7 @@
Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 0);
mZenModeHelperSpy.mIsBootComplete = true;
mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0, 0);
- mZenModeHelperSpy.setZenModeSetting(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+ mZenModeHelperSpy.setZenModeSetting(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
verify(mZenModeHelperSpy, times(1)).createZenUpgradeNotification();
verify(mNotificationManager, times(1)).notify(eq(ZenModeHelper.TAG),
@@ -494,7 +516,7 @@
Settings.Secure.putInt(mContentResolver, Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 0);
mZenModeHelperSpy.mIsBootComplete = true;
- mZenModeHelperSpy.setZenModeSetting(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+ mZenModeHelperSpy.setZenModeSetting(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
verify(mZenModeHelperSpy, never()).createZenUpgradeNotification();
verify(mNotificationManager, never()).notify(eq(ZenModeHelper.TAG),
@@ -507,7 +529,7 @@
Settings.Secure.putInt(mContentResolver, Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 1);
mZenModeHelperSpy.mIsBootComplete = true;
- mZenModeHelperSpy.setZenModeSetting(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+ mZenModeHelperSpy.setZenModeSetting(ZEN_MODE_IMPORTANT_INTERRUPTIONS);
verify(mZenModeHelperSpy, never()).createZenUpgradeNotification();
verify(mNotificationManager, never()).notify(eq(ZenModeHelper.TAG),
@@ -524,7 +546,7 @@
// 1. Current ringer is normal
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
// Set zen to priority-only with all notification sounds muted (so ringer will be muted)
- mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowReminders = false;
mZenModeHelperSpy.mConfig.allowCalls = false;
mZenModeHelperSpy.mConfig.allowMessages = false;
@@ -568,7 +590,7 @@
// ringtone, notification and system streams are affected by ringer mode
mZenModeHelperSpy.mConfig.allowAlarms = true;
mZenModeHelperSpy.mConfig.allowReminders = true;
- mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
ZenModeHelper.RingerModeDelegate ringerModeDelegateRingerMuted =
mZenModeHelperSpy.new RingerModeDelegate();
@@ -615,7 +637,7 @@
// 1. Current ringer is normal
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
- mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowReminders = true;
// 2. apply priority only zen - verify ringer is normal
@@ -640,7 +662,7 @@
// 1. Current ringer is silent
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
- mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowReminders = true;
// 2. apply priority only zen - verify ringer is silent
@@ -666,7 +688,7 @@
// 1. Current ringer is normal
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
// Set zen to priority-only with all notification sounds muted (so ringer will be muted)
- mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowReminders = true;
// 2. apply priority only zen - verify zen will still be normal
@@ -728,7 +750,7 @@
// apply zen off multiple times - verify ringer is not set to normal
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
- mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
for (int i = 0; i < 3; i++) {
// if zen doesn't change, zen should not reapply itself to the ringer
mZenModeHelperSpy.evaluateZenMode("test", true);
@@ -756,7 +778,7 @@
// apply zen off multiple times - verify ringer is not set to normal
when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
- mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
for (int i = 0; i < 3; i++) {
// if zen doesn't change, zen should not reapply itself to the ringer
mZenModeHelperSpy.evaluateZenMode("test", true);
@@ -768,7 +790,7 @@
@Test
public void testParcelConfig() {
- mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
mZenModeHelperSpy.mConfig.allowMedia = false;
mZenModeHelperSpy.mConfig.allowSystem = false;
@@ -792,7 +814,7 @@
@Test
public void testWriteXml() throws Exception {
- mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
mZenModeHelperSpy.mConfig.allowMedia = false;
mZenModeHelperSpy.mConfig.allowSystem = false;
@@ -806,7 +828,7 @@
mZenModeHelperSpy.mConfig.suppressedVisualEffects = SUPPRESSED_EFFECT_BADGE;
mZenModeHelperSpy.mConfig.manualRule = new ZenModeConfig.ZenRule();
mZenModeHelperSpy.mConfig.manualRule.zenMode =
- Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.manualRule.component = new ComponentName("a", "a");
mZenModeHelperSpy.mConfig.manualRule.pkg = "a";
mZenModeHelperSpy.mConfig.manualRule.enabled = true;
@@ -822,6 +844,102 @@
}
@Test
+ public void testProto() {
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mConfig.manualRule = new ZenModeConfig.ZenRule();
+
+ int n = mZenModeHelperSpy.mConfig.automaticRules.size();
+ List<String> ids = new ArrayList<>(n);
+ for (ZenModeConfig.ZenRule rule : mZenModeHelperSpy.mConfig.automaticRules.values()) {
+ ids.add(rule.id);
+ }
+ ids.add("");
+
+ List<StatsEvent> events = new LinkedList<>();
+ mZenModeHelperSpy.pullRules(events);
+ assertEquals(n + 1, events.size());
+ for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) {
+ if (builder.getAtomId() == DND_MODE_RULE) {
+ if (builder.getInt(ZEN_MODE_FIELD_NUMBER) == DNDModeProto.ROOT_CONFIG) {
+ assertTrue(builder.getBoolean(ENABLED_FIELD_NUMBER));
+ assertFalse(builder.getBoolean(CHANNELS_BYPASSING_FIELD_NUMBER));
+ }
+ assertEquals(Process.SYSTEM_UID, builder.getInt(UID_FIELD_NUMBER));
+ assertTrue(builder.getBooleanAnnotation(UID_FIELD_NUMBER, ANNOTATION_ID_IS_UID));
+ String name = (String) builder.getValue(ID_FIELD_NUMBER);
+ assertTrue("unexpected rule id", ids.contains(name));
+ ids.remove(name);
+ } else {
+ fail("unexpected atom id: " + builder.getAtomId());
+ }
+ }
+ assertEquals("extra rule in output", 0, ids.size());
+ }
+
+ @Test
+ public void testProtoWithAutoRule() throws Exception {
+ setupZenConfig();
+ // one enabled automatic rule
+ mZenModeHelperSpy.mConfig.automaticRules = getCustomAutomaticRules(ZEN_MODE_FOR_TESTING);
+
+ List<StatsEvent> events = new LinkedList<>();
+ mZenModeHelperSpy.pullRules(events);
+
+ boolean foundCustomEvent = false;
+ for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) {
+ if (builder.getAtomId() == DND_MODE_RULE) {
+ if (ZEN_MODE_FOR_TESTING == builder.getInt(ZEN_MODE_FIELD_NUMBER)) {
+ foundCustomEvent = true;
+ assertEquals(0, builder.getInt(UID_FIELD_NUMBER));
+ assertTrue(builder.getBoolean(ENABLED_FIELD_NUMBER));
+ }
+ } else {
+ fail("unexpected atom id: " + builder.getAtomId());
+ }
+ }
+ assertTrue("couldn't find custom rule", foundCustomEvent);
+ }
+
+ @Test
+ public void testProtoRedactsIds() throws Exception {
+ setupZenConfig();
+ // one enabled automatic rule
+ mZenModeHelperSpy.mConfig.automaticRules = getCustomAutomaticRules();
+
+ List<StatsEvent> events = new LinkedList<>();
+ mZenModeHelperSpy.pullRules(events);
+
+ boolean foundCustomEvent = false;
+ for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) {
+ if (builder.getAtomId() == DND_MODE_RULE
+ && "customRule".equals(builder.getString(ID_FIELD_NUMBER))) {
+ fail("non-default IDs should be redacted");
+ }
+ }
+ }
+
+ @Test
+ public void testProtoWithManualRule() throws Exception {
+ setupZenConfig();
+ mZenModeHelperSpy.mConfig.automaticRules = getCustomAutomaticRules();
+ mZenModeHelperSpy.mConfig.manualRule = new ZenModeConfig.ZenRule();
+ mZenModeHelperSpy.mConfig.manualRule.enabled = true;
+ mZenModeHelperSpy.mConfig.manualRule.enabler = "com.enabler";
+
+ List<StatsEvent> events = new LinkedList<>();
+ mZenModeHelperSpy.pullRules(events);
+
+ boolean foundManualRule = false;
+ for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) {
+ if (builder.getAtomId() == DND_MODE_RULE
+ && ZenModeConfig.MANUAL_RULE_ID.equals(builder.getString(ID_FIELD_NUMBER))) {
+ assertEquals(0, builder.getInt(UID_FIELD_NUMBER));
+ foundManualRule = true;
+ }
+ }
+ assertTrue("couldn't find manual rule", foundManualRule); }
+
+ @Test
public void testWriteXml_onlyBackupsTargetUser() throws Exception {
// Setup configs for user 10 and 11.
setupZenConfig();
@@ -906,7 +1024,7 @@
customRule.creationTime = 0;
customRule.id = "customRule";
customRule.name = "Custom Rule";
- customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ customRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
customRule.conditionId = ZenModeConfig.toScheduleConditionId(customRuleInfo);
customRule.configurationActivity =
new ComponentName("android", "ScheduleConditionProvider");
@@ -951,7 +1069,7 @@
customRule.creationTime = 0;
customRule.id = ruleId;
customRule.name = "Custom Rule";
- customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ customRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
customRule.conditionId = ZenModeConfig.toScheduleConditionId(customRuleInfo);
customRule.configurationActivity =
new ComponentName("android", "ScheduleConditionProvider");
@@ -986,7 +1104,7 @@
final ScheduleInfo weeknights = new ScheduleInfo();
customRule.enabled = true;
customRule.name = "Custom Rule";
- customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ customRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
customRule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights);
customRule.component = new ComponentName("android", "ScheduleConditionProvider");
enabledAutoRule.put("customRule", customRule);
@@ -1151,7 +1269,7 @@
final ScheduleInfo weeknights = new ScheduleInfo();
customRule.enabled = false;
customRule.name = "Custom Rule";
- customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ customRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
customRule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights);
customRule.component = new ComponentName("android", "ScheduleConditionProvider");
disabledAutoRule.put("customRule", customRule);
@@ -1187,7 +1305,7 @@
final ScheduleInfo customRuleInfo = new ScheduleInfo();
customRule.enabled = false;
customRule.name = "Custom Rule";
- customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ customRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
customRule.conditionId = ZenModeConfig.toScheduleConditionId(customRuleInfo);
customRule.component = new ComponentName("android", "ScheduleConditionProvider");
customRule.zenPolicy = new ZenPolicy.Builder()
@@ -1200,7 +1318,7 @@
final ScheduleInfo defaultScheduleRuleInfo = new ScheduleInfo();
defaultScheduleRule.enabled = false;
defaultScheduleRule.name = "Default Schedule Rule";
- defaultScheduleRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ defaultScheduleRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
defaultScheduleRule.conditionId = ZenModeConfig.toScheduleConditionId(
defaultScheduleRuleInfo);
customRule.component = new ComponentName("android", "ScheduleConditionProvider");
@@ -1238,7 +1356,7 @@
final ScheduleInfo customRuleInfo = new ScheduleInfo();
customRule.enabled = false;
customRule.name = "Custom Rule";
- customRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ customRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
customRule.conditionId = ZenModeConfig.toScheduleConditionId(customRuleInfo);
customRule.component = new ComponentName("android", "ScheduleConditionProvider");
customRule.zenPolicy = new ZenPolicy.Builder()
@@ -1251,7 +1369,7 @@
final ScheduleInfo defaultScheduleRuleInfo = new ScheduleInfo();
defaultScheduleRule.enabled = false;
defaultScheduleRule.name = "Default Schedule Rule";
- defaultScheduleRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ defaultScheduleRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
defaultScheduleRule.conditionId = ZenModeConfig.toScheduleConditionId(
defaultScheduleRuleInfo);
defaultScheduleRule.id = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID;
@@ -1265,7 +1383,7 @@
final ScheduleInfo defaultEventRuleInfo = new ScheduleInfo();
defaultEventRule.enabled = false;
defaultEventRule.name = "Default Event Rule";
- defaultEventRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ defaultEventRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
defaultEventRule.conditionId = ZenModeConfig.toScheduleConditionId(
defaultEventRuleInfo);
defaultEventRule.id = ZenModeConfig.EVENTS_DEFAULT_RULE_ID;
@@ -1295,6 +1413,10 @@
assertTrue(rules.containsKey("customRule"));
setupZenConfigMaintained();
+
+ List<StatsEvent> events = new LinkedList<>();
+ mZenModeHelperSpy.pullRules(events);
+ assertEquals(4, events.size());
}
@Test
@@ -1323,10 +1445,12 @@
@Test
public void testEmptyDefaultRulesMap() {
+ List<StatsEvent> events = new LinkedList<>();
ZenModeConfig config = new ZenModeConfig();
config.automaticRules = new ArrayMap<>();
mZenModeHelperSpy.mConfig = config;
mZenModeHelperSpy.updateDefaultZenRules(); // shouldn't throw null pointer
+ mZenModeHelperSpy.pullRules(events); // shouldn't throw null pointer
}
@Test
@@ -1342,7 +1466,7 @@
updatedDefaultRule.creationTime = 0;
updatedDefaultRule.id = SCHEDULE_DEFAULT_RULE_ID;
updatedDefaultRule.name = "Schedule Default Rule";
- updatedDefaultRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ updatedDefaultRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
updatedDefaultRule.conditionId = ZenModeConfig.toScheduleConditionId(new ScheduleInfo());
updatedDefaultRule.component = new ComponentName("android", "ScheduleConditionProvider");
@@ -1368,7 +1492,7 @@
updatedDefaultRule.creationTime = 0;
updatedDefaultRule.id = SCHEDULE_DEFAULT_RULE_ID;
updatedDefaultRule.name = "Schedule Default Rule";
- updatedDefaultRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ updatedDefaultRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
updatedDefaultRule.conditionId = ZenModeConfig.toScheduleConditionId(new ScheduleInfo());
updatedDefaultRule.component = new ComponentName("android", "ScheduleConditionProvider");
@@ -1395,7 +1519,7 @@
customDefaultRule.creationTime = 0;
customDefaultRule.id = SCHEDULE_DEFAULT_RULE_ID;
customDefaultRule.name = "Schedule Default Rule";
- customDefaultRule.zenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ customDefaultRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
customDefaultRule.conditionId = ZenModeConfig.toScheduleConditionId(new ScheduleInfo());
customDefaultRule.component = new ComponentName("android", "ScheduleConditionProvider");
@@ -1433,7 +1557,7 @@
}
private void setupZenConfig() {
- mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+ mZenModeHelperSpy.mZenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
mZenModeHelperSpy.mConfig.allowMedia = false;
mZenModeHelperSpy.mConfig.allowSystem = false;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenPolicyTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenPolicyTest.java
index a0ee417..b16ca8b 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenPolicyTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenPolicyTest.java
@@ -17,14 +17,18 @@
package com.android.server.notification;
import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.fail;
import android.service.notification.ZenPolicy;
+import android.service.notification.nano.DNDPolicyProto;
import android.test.suitebuilder.annotation.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.UiServiceTestCase;
+import com.google.protobuf.nano.InvalidProtocolBufferNanoException;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -190,6 +194,7 @@
ZenPolicy policy = builder.build();
assertEquals(ZenPolicy.STATE_UNSET, policy.getPriorityCategoryMessages());
assertEquals(ZenPolicy.PEOPLE_TYPE_UNSET, policy.getPriorityMessageSenders());
+ assertProtoMatches(policy, policy.toProto());
}
@Test
@@ -201,6 +206,7 @@
ZenPolicy policy = builder.build();
assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryCalls());
assertEquals(ZenPolicy.PEOPLE_TYPE_ANYONE, policy.getPriorityCallSenders());
+ assertProtoMatches(policy, policy.toProto());
}
@Test
@@ -210,6 +216,7 @@
ZenPolicy policy = builder.build();
assertAllPriorityCategoriesUnsetExcept(policy, -1);
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
}
@Test
@@ -221,12 +228,14 @@
assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_REMINDERS);
assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryReminders());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
builder.allowReminders(false);
policy = builder.build();
assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_REMINDERS);
assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategoryReminders());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
}
@Test
@@ -238,12 +247,14 @@
assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_EVENTS);
assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryEvents());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
builder.allowEvents(false);
policy = builder.build();
assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_EVENTS);
assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategoryEvents());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
}
@Test
@@ -256,6 +267,7 @@
assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryMessages());
assertEquals(ZenPolicy.PEOPLE_TYPE_ANYONE, policy.getPriorityMessageSenders());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
builder.allowMessages(ZenPolicy.PEOPLE_TYPE_CONTACTS);
policy = builder.build();
@@ -263,6 +275,7 @@
assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryMessages());
assertEquals(ZenPolicy.PEOPLE_TYPE_CONTACTS, policy.getPriorityMessageSenders());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
builder.allowMessages(ZenPolicy.PEOPLE_TYPE_STARRED);
policy = builder.build();
@@ -270,6 +283,7 @@
assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryMessages());
assertEquals(ZenPolicy.PEOPLE_TYPE_STARRED, policy.getPriorityMessageSenders());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
builder.allowMessages(ZenPolicy.PEOPLE_TYPE_NONE);
policy = builder.build();
@@ -277,11 +291,13 @@
assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategoryMessages());
assertEquals(ZenPolicy.PEOPLE_TYPE_NONE, policy.getPriorityMessageSenders());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
builder.allowMessages(ZenPolicy.PEOPLE_TYPE_UNSET);
policy = builder.build();
assertAllPriorityCategoriesUnsetExcept(policy, -1);
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
}
@Test
@@ -294,6 +310,7 @@
assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryCalls());
assertEquals(ZenPolicy.PEOPLE_TYPE_ANYONE, policy.getPriorityCallSenders());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
builder.allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS);
policy = builder.build();
@@ -301,6 +318,7 @@
assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryCalls());
assertEquals(ZenPolicy.PEOPLE_TYPE_CONTACTS, policy.getPriorityCallSenders());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
builder.allowCalls(ZenPolicy.PEOPLE_TYPE_STARRED);
policy = builder.build();
@@ -308,6 +326,7 @@
assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryCalls());
assertEquals(ZenPolicy.PEOPLE_TYPE_STARRED, policy.getPriorityCallSenders());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
builder.allowCalls(ZenPolicy.PEOPLE_TYPE_NONE);
policy = builder.build();
@@ -315,11 +334,13 @@
assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategoryCalls());
assertEquals(ZenPolicy.PEOPLE_TYPE_NONE, policy.getPriorityCallSenders());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
builder.allowCalls(ZenPolicy.PEOPLE_TYPE_UNSET);
policy = builder.build();
assertAllPriorityCategoriesUnsetExcept(policy, -1);
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
}
@Test
@@ -331,12 +352,14 @@
assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_REPEAT_CALLERS);
assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryRepeatCallers());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
builder.allowRepeatCallers(false);
policy = builder.build();
assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_REPEAT_CALLERS);
assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategoryRepeatCallers());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
}
@Test
@@ -348,12 +371,14 @@
assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_ALARMS);
assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryAlarms());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
builder.allowAlarms(false);
policy = builder.build();
assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_ALARMS);
assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategoryAlarms());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
}
@Test
@@ -365,12 +390,14 @@
assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_MEDIA);
assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategoryMedia());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
builder.allowMedia(false);
policy = builder.build();
assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_MEDIA);
assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategoryMedia());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
}
@Test
@@ -382,12 +409,119 @@
assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_SYSTEM);
assertEquals(ZenPolicy.STATE_ALLOW, policy.getPriorityCategorySystem());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
builder.allowSystem(false);
policy = builder.build();
assertAllPriorityCategoriesUnsetExcept(policy, ZenPolicy.PRIORITY_CATEGORY_SYSTEM);
assertEquals(ZenPolicy.STATE_DISALLOW, policy.getPriorityCategorySystem());
assertAllVisualEffectsUnsetExcept(policy, -1);
+ assertProtoMatches(policy, policy.toProto());
+ }
+
+ @Test
+ public void tesShowFullScreenIntent() {
+ ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+ builder.showFullScreenIntent(true);
+ ZenPolicy policy = builder.build();
+ assertAllVisualEffectsUnsetExcept(policy, ZenPolicy.VISUAL_EFFECT_FULL_SCREEN_INTENT);
+ assertProtoMatches(policy, policy.toProto());
+
+ builder.showFullScreenIntent(false);
+ policy = builder.build();
+ assertAllVisualEffectsUnsetExcept(policy, ZenPolicy.VISUAL_EFFECT_FULL_SCREEN_INTENT);
+ assertProtoMatches(policy, policy.toProto());
+ }
+
+ @Test
+ public void tesShowLights() {
+ ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+ builder.showLights(true);
+ ZenPolicy policy = builder.build();
+ assertAllVisualEffectsUnsetExcept(policy, ZenPolicy.VISUAL_EFFECT_LIGHTS);
+ assertProtoMatches(policy, policy.toProto());
+
+ builder.showLights(false);
+ policy = builder.build();
+ assertAllVisualEffectsUnsetExcept(policy, ZenPolicy.VISUAL_EFFECT_LIGHTS);
+ assertProtoMatches(policy, policy.toProto());
+ }
+
+ @Test
+ public void tesShowPeeking() {
+ ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+ builder.showPeeking(true);
+ ZenPolicy policy = builder.build();
+ assertAllVisualEffectsUnsetExcept(policy, ZenPolicy.VISUAL_EFFECT_PEEK);
+ assertProtoMatches(policy, policy.toProto());
+
+ builder.showPeeking(false);
+ policy = builder.build();
+ assertAllVisualEffectsUnsetExcept(policy, ZenPolicy.VISUAL_EFFECT_PEEK);
+ assertProtoMatches(policy, policy.toProto());
+ }
+
+ @Test
+ public void tesShowStatusBarIcons() {
+ ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+ builder.showStatusBarIcons(true);
+ ZenPolicy policy = builder.build();
+ assertAllVisualEffectsUnsetExcept(policy, ZenPolicy.VISUAL_EFFECT_STATUS_BAR);
+ assertProtoMatches(policy, policy.toProto());
+
+ builder.showStatusBarIcons(false);
+ policy = builder.build();
+ assertAllVisualEffectsUnsetExcept(policy, ZenPolicy.VISUAL_EFFECT_STATUS_BAR);
+ assertProtoMatches(policy, policy.toProto());
+ }
+
+ @Test
+ public void tesShowBadges() {
+ ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+ builder.showBadges(true);
+ ZenPolicy policy = builder.build();
+ assertAllVisualEffectsUnsetExcept(policy, ZenPolicy.VISUAL_EFFECT_BADGE);
+ assertProtoMatches(policy, policy.toProto());
+
+ builder.showBadges(false);
+ policy = builder.build();
+ assertAllVisualEffectsUnsetExcept(policy, ZenPolicy.VISUAL_EFFECT_BADGE);
+ assertProtoMatches(policy, policy.toProto());
+ }
+
+ @Test
+ public void tesShowInAmbientDisplay() {
+ ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+ builder.showInAmbientDisplay(true);
+ ZenPolicy policy = builder.build();
+ assertAllVisualEffectsUnsetExcept(policy, ZenPolicy.VISUAL_EFFECT_AMBIENT);
+ assertProtoMatches(policy, policy.toProto());
+
+ builder.showInAmbientDisplay(false);
+ policy = builder.build();
+ assertAllVisualEffectsUnsetExcept(policy, ZenPolicy.VISUAL_EFFECT_AMBIENT);
+ assertProtoMatches(policy, policy.toProto());
+ }
+
+ @Test
+ public void tesShowInNotificationList() {
+ ZenPolicy.Builder builder = new ZenPolicy.Builder();
+
+ builder.showInNotificationList(true);
+ ZenPolicy policy = builder.build();
+ assertAllVisualEffectsUnsetExcept(policy, ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST);
+ assertProtoMatches(policy, policy.toProto());
+
+ builder.showInNotificationList(false);
+ policy = builder.build();
+ assertAllVisualEffectsUnsetExcept(policy, ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST);
+ assertProtoMatches(policy, policy.toProto());
}
private void assertAllPriorityCategoriesUnsetExcept(ZenPolicy policy, int except) {
@@ -453,4 +587,35 @@
assertEquals(ZenPolicy.STATE_UNSET, policy.getVisualEffectNotificationList());
}
}
+
+ private void assertProtoMatches(ZenPolicy policy, byte[] bytes) {
+ try {
+ DNDPolicyProto proto = DNDPolicyProto.parseFrom(bytes);
+
+ assertEquals(policy.getPriorityCategoryCalls(), proto.calls);
+ assertEquals(policy.getPriorityCategoryRepeatCallers(), proto.repeatCallers);
+ assertEquals(policy.getPriorityCategoryMessages(), proto.messages);
+ assertEquals(policy.getPriorityCategoryConversations(), proto.conversations);
+ assertEquals(policy.getPriorityCategoryReminders(), proto.reminders);
+ assertEquals(policy.getPriorityCategoryEvents(), proto.events);
+ assertEquals(policy.getPriorityCategoryAlarms(), proto.alarms);
+ assertEquals(policy.getPriorityCategoryMedia(), proto.media);
+ assertEquals(policy.getPriorityCategorySystem(), proto.system);
+
+ assertEquals(policy.getVisualEffectFullScreenIntent(), proto.fullscreen);
+ assertEquals(policy.getVisualEffectLights(), proto.lights);
+ assertEquals(policy.getVisualEffectPeek(), proto.peek);
+ assertEquals(policy.getVisualEffectStatusBar(), proto.statusBar);
+ assertEquals(policy.getVisualEffectBadge(), proto.badge);
+ assertEquals(policy.getVisualEffectAmbient(), proto.ambient);
+ assertEquals(policy.getVisualEffectNotificationList(), proto.notificationList);
+
+ assertEquals(policy.getPriorityCallSenders(), proto.allowCallsFrom);
+ assertEquals(policy.getPriorityMessageSenders(), proto.allowMessagesFrom);
+ assertEquals(policy.getPriorityConversationSenders(), proto.allowConversationsFrom);
+ } catch (InvalidProtocolBufferNanoException e) {
+ fail("could not parse proto bytes");
+ }
+
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index bd616a3..64b5eca 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
@@ -111,7 +110,7 @@
final ActivityStack stack = new StackBuilder(mRootWindowContainer).build();
final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
ClientLifecycleManager lifecycleManager = mService.getLifecycleManager();
- doNothing().when(lifecycleManager).scheduleTransaction(any());
+ doReturn(false).when(activity).inPinnedWindowingMode();
doReturn(false).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
mService.requestPictureInPictureMode(activity.token);
@@ -120,6 +119,19 @@
verify(lifecycleManager, times(0)).scheduleTransaction(any());
}
+ @Test(expected = IllegalStateException.class)
+ public void testOnPictureInPictureRequested_alreadyInPIPMode() throws RemoteException {
+ final ActivityStack stack = new StackBuilder(mRootWindowContainer).build();
+ final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
+ ClientLifecycleManager lifecycleManager = mService.getLifecycleManager();
+ doReturn(true).when(activity).inPinnedWindowingMode();
+
+ mService.requestPictureInPictureMode(activity.token);
+
+ // Check that no transactions with enter pip requests are made.
+ verify(lifecycleManager, times(0)).scheduleTransaction(any());
+ }
+
@Test
public void testDisplayWindowListener() {
final ArrayList<Integer> added = new ArrayList<>();
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 2e4e7f5..7b86b08 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -1381,4 +1381,26 @@
public String getWapiCertSuite() {
return getFieldValue(WAPI_CERT_SUITE_KEY);
}
+
+ /**
+ * Method determines whether the Enterprise configuration is insecure. An insecure
+ * configuration is one where EAP method requires a CA certification, i.e. PEAP, TLS, or
+ * TTLS, and any of the following conditions are met:
+ * - Both certificate and CA path are not configured.
+ * - Both alternative subject match and domain suffix match are not set.
+ *
+ * Note: this method does not exhaustively check security of the configuration - i.e. a return
+ * value of {@code false} is not a guarantee that the configuration is secure.
+ * @hide
+ */
+ public boolean isInsecure() {
+ if (mEapMethod != Eap.PEAP && mEapMethod != Eap.TLS && mEapMethod != Eap.TTLS) {
+ return false;
+ }
+ if (!mIsAppInstalledCaCert && TextUtils.isEmpty(getCaPath())) {
+ return true;
+ }
+ return TextUtils.isEmpty(getAltSubjectMatch()) && TextUtils.isEmpty(
+ getDomainSuffixMatch());
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 8c494943..4d3a2c0 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -257,28 +257,38 @@
/**
* Set the associated enterprise configuration for this network. Needed for authenticating
- * to WPA2-EAP networks. See {@link WifiEnterpriseConfig} for description.
+ * to WPA2 enterprise networks. See {@link WifiEnterpriseConfig} for description.
*
* @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
* @return Instance of {@link Builder} to enable chaining of the builder method.
+ * @throws IllegalArgumentException if configuration CA certificate or
+ * AltSubjectMatch/DomainSuffixMatch is not set.
*/
public @NonNull Builder setWpa2EnterpriseConfig(
@NonNull WifiEnterpriseConfig enterpriseConfig) {
checkNotNull(enterpriseConfig);
+ if (enterpriseConfig.isInsecure()) {
+ throw new IllegalArgumentException("Enterprise configuration is insecure");
+ }
mWpa2EnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
return this;
}
/**
* Set the associated enterprise configuration for this network. Needed for authenticating
- * to WPA3-SuiteB networks. See {@link WifiEnterpriseConfig} for description.
+ * to WPA3 enterprise networks. See {@link WifiEnterpriseConfig} for description.
*
* @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
* @return Instance of {@link Builder} to enable chaining of the builder method.
+ * @throws IllegalArgumentException if configuration CA certificate or
+ * AltSubjectMatch/DomainSuffixMatch is not set.
*/
public @NonNull Builder setWpa3EnterpriseConfig(
@NonNull WifiEnterpriseConfig enterpriseConfig) {
checkNotNull(enterpriseConfig);
+ if (enterpriseConfig.isInsecure()) {
+ throw new IllegalArgumentException("Enterprise configuration is insecure");
+ }
mWpa3EnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
return this;
}
diff --git a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
index 320c187..268645c 100644
--- a/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiEnterpriseConfigTest.java
@@ -47,6 +47,7 @@
public static final String KEYSTORE_URI = "keystore://";
public static final String CA_CERT_PREFIX = KEYSTORE_URI + Credentials.CA_CERTIFICATE;
public static final String KEYSTORES_URI = "keystores://";
+ private static final String TEST_DOMAIN_SUFFIX_MATCH = "domainSuffixMatch";
private WifiEnterpriseConfig mEnterpriseConfig;
@@ -540,4 +541,30 @@
mEnterpriseConfig.setEapMethod(Eap.UNAUTH_TLS);
assertEquals(null, getSupplicantPhase2Method());
}
+
+ @Test
+ public void testIsEnterpriseConfigSecure() {
+ WifiEnterpriseConfig baseConfig = new WifiEnterpriseConfig();
+ baseConfig.setEapMethod(Eap.PEAP);
+ baseConfig.setPhase2Method(Phase2.MSCHAPV2);
+ assertTrue(baseConfig.isInsecure());
+
+ WifiEnterpriseConfig noMatchConfig = new WifiEnterpriseConfig(baseConfig);
+ noMatchConfig.setCaCertificate(FakeKeys.CA_CERT0);
+ // Missing match is insecure.
+ assertTrue(noMatchConfig.isInsecure());
+
+ WifiEnterpriseConfig noCaConfig = new WifiEnterpriseConfig(baseConfig);
+ noCaConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+ // Missing CA certificate is insecure.
+ assertTrue(noCaConfig.isInsecure());
+
+ WifiEnterpriseConfig secureConfig = new WifiEnterpriseConfig();
+ secureConfig.setEapMethod(Eap.PEAP);
+ secureConfig.setPhase2Method(Phase2.MSCHAPV2);
+ secureConfig.setCaCertificate(FakeKeys.CA_CERT0);
+ secureConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+ assertFalse(secureConfig.isInsecure());
+ }
+
}
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index d1d1c61..16b4ad0 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -38,6 +38,7 @@
private static final String TEST_PRESHARED_KEY = "Test123";
private static final String TEST_FQDN = "fqdn";
private static final String TEST_WAPI_CERT_SUITE = "suite";
+ private static final String TEST_DOMAIN_SUFFIX_MATCH = "domainSuffixMatch";
/**
* Validate correctness of WifiNetworkSuggestion object created by
@@ -208,6 +209,8 @@
WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0);
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
.setSsid(TEST_SSID)
@@ -230,6 +233,40 @@
}
/**
+ * Ensure create enterprise suggestion requires CA, when CA certificate is missing, will throw
+ * an exception.
+ */
+ @Test (expected = IllegalArgumentException.class)
+ public void testWifiNetworkSuggestionBuilderForEapNetworkWithoutCa() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC);
+ enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH);
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa2EnterpriseConfig(enterpriseConfig)
+ .build();
+ }
+
+ /**
+ * Ensure create enterprise suggestion requires CA, when both domain suffix and alt subject
+ * match are missing, will throw an exception.
+ */
+ @Test (expected = IllegalArgumentException.class)
+ public void testWifiNetworkSuggestionBuilderForEapNetworkWithoutMatch() {
+ WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig();
+ enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
+ enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC);
+ enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0);
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa3EnterpriseConfig(enterpriseConfig)
+ .build();
+ }
+
+ /**
* Validate correctness of WifiNetworkSuggestion object created by
* {@link WifiNetworkSuggestion.Builder#build()} for WAPI-PSK network.
*/