Merge "Add tracing for receiver registration and un-registration." into main
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index 3e5f1cb..fa11278 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -379,6 +379,7 @@
aconfig_declarations {
name: "com.android.internal.os.flags-aconfig",
package: "com.android.internal.os",
+ container: "system",
srcs: ["core/java/com/android/internal/os/flags.aconfig"],
}
@@ -853,6 +854,7 @@
aconfig_declarations {
name: "com.android.server.contextualsearch.flags-aconfig",
package: "com.android.server.contextualsearch.flags",
+ container: "system",
srcs: ["services/contextualsearch/flags/flags.aconfig"],
}
diff --git a/cmds/uinput/src/com/android/commands/uinput/Device.java b/cmds/uinput/src/com/android/commands/uinput/Device.java
index 7e99c92..2cac6313 100644
--- a/cmds/uinput/src/com/android/commands/uinput/Device.java
+++ b/cmds/uinput/src/com/android/commands/uinput/Device.java
@@ -223,7 +223,7 @@
break;
}
long offsetMicros = args.argl1;
- if (mLastInjectTimestampMicros == -1 || offsetMicros == -1) {
+ if (mLastInjectTimestampMicros == -1) {
// There's often a delay of a few milliseconds between the time specified to
// Handler.sendMessageAtTime and the handler actually being called, due to
// the way threads are scheduled. We don't take this into account when
@@ -239,6 +239,9 @@
// To prevent this, we need to use the time at which we scheduled this first
// batch, rather than the actual current time.
mLastInjectTimestampMicros = args.argl2 / 1000;
+ } else if (offsetMicros == -1) {
+ // No timestamp offset is specified for this event, so use the current time.
+ mLastInjectTimestampMicros = SystemClock.uptimeNanos() / 1000;
} else {
mLastInjectTimestampMicros += offsetMicros;
}
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 443a6c0e..5a3ff83 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -263,6 +263,7 @@
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void setHistoryParameters(int, long, int);
method @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES) public void setMode(int, int, String, int);
method public static int strOpToOp(@NonNull String);
+ method public int unsafeCheckOpRawNoThrow(@NonNull String, @NonNull android.content.AttributionSource);
field public static final int ATTRIBUTION_CHAIN_ID_NONE = -1; // 0xffffffff
field public static final int ATTRIBUTION_FLAGS_NONE = 0; // 0x0
field public static final int ATTRIBUTION_FLAG_ACCESSOR = 1; // 0x1
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index f4d1304..b3312a8 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -8788,6 +8788,18 @@
* Does not throw a security exception, does not translate {@link #MODE_FOREGROUND}.
* @hide
*/
+ @TestApi
+ @SuppressLint("UnflaggedApi") // @TestApi without associated feature.
+ public int unsafeCheckOpRawNoThrow(
+ @NonNull String op, @NonNull AttributionSource attributionSource) {
+ return unsafeCheckOpRawNoThrow(strOpToOp(op), attributionSource);
+ }
+
+ /**
+ * Returns the <em>raw</em> mode associated with the op.
+ * Does not throw a security exception, does not translate {@link #MODE_FOREGROUND}.
+ * @hide
+ */
public int unsafeCheckOpRawNoThrow(int op, int uid, @NonNull String packageName) {
return unsafeCheckOpRawNoThrow(op, uid, packageName, Context.DEVICE_ID_DEFAULT);
}
@@ -8798,8 +8810,8 @@
if (virtualDeviceId == Context.DEVICE_ID_DEFAULT) {
return mService.checkOperationRaw(op, uid, packageName, null);
} else {
- return mService.checkOperationRawForDevice(op, uid, packageName, null,
- Context.DEVICE_ID_DEFAULT);
+ return mService.checkOperationRawForDevice(
+ op, uid, packageName, null, virtualDeviceId);
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index f7e0e9f..714454b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -93,7 +93,10 @@
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
+import android.text.style.StrikethroughSpan;
+import android.text.style.StyleSpan;
import android.text.style.TextAppearanceSpan;
+import android.text.style.UnderlineSpan;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
@@ -765,11 +768,24 @@
MessagingStyle.class, CallStyle.class);
/** @hide */
- @IntDef(flag = true, prefix = { "FLAG_" }, value = {FLAG_SHOW_LIGHTS, FLAG_ONGOING_EVENT,
- FLAG_INSISTENT, FLAG_ONLY_ALERT_ONCE,
- FLAG_AUTO_CANCEL, FLAG_NO_CLEAR, FLAG_FOREGROUND_SERVICE, FLAG_HIGH_PRIORITY,
- FLAG_LOCAL_ONLY, FLAG_GROUP_SUMMARY, FLAG_AUTOGROUP_SUMMARY, FLAG_BUBBLE,
- FLAG_USER_INITIATED_JOB})
+ @IntDef(flag = true, prefix = {"FLAG_"}, value = {
+ FLAG_SHOW_LIGHTS,
+ FLAG_ONGOING_EVENT,
+ FLAG_INSISTENT,
+ FLAG_ONLY_ALERT_ONCE,
+ FLAG_AUTO_CANCEL,
+ FLAG_NO_CLEAR,
+ FLAG_FOREGROUND_SERVICE,
+ FLAG_HIGH_PRIORITY,
+ FLAG_LOCAL_ONLY,
+ FLAG_GROUP_SUMMARY,
+ FLAG_AUTOGROUP_SUMMARY,
+ FLAG_CAN_COLORIZE,
+ FLAG_BUBBLE,
+ FLAG_NO_DISMISS,
+ FLAG_FSI_REQUESTED_BUT_DENIED,
+ FLAG_USER_INITIATED_JOB
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface NotificationFlags{};
@@ -3154,9 +3170,6 @@
+ " instance is a custom Parcelable and not allowed in Notification");
return cs.toString();
}
- if (Flags.cleanUpSpansAndNewLines()) {
- return stripStyling(cs);
- }
return removeTextSizeSpans(cs);
}
@@ -3779,10 +3792,10 @@
if (this.tickerText != null) {
sb.append(" tick");
}
- sb.append(" defaults=0x");
- sb.append(Integer.toHexString(this.defaults));
- sb.append(" flags=0x");
- sb.append(Integer.toHexString(this.flags));
+ sb.append(" defaults=");
+ sb.append(defaultsToString(this.defaults));
+ sb.append(" flags=");
+ sb.append(flagsToString(this.flags));
sb.append(String.format(" color=0x%08x", this.color));
if (this.category != null) {
sb.append(" category=");
@@ -3851,6 +3864,124 @@
}
/**
+ * {@hide}
+ */
+ public static String flagsToString(@NotificationFlags int flags) {
+ final List<String> flagStrings = new ArrayList<String>();
+ if ((flags & FLAG_SHOW_LIGHTS) != 0) {
+ flagStrings.add("SHOW_LIGHTS");
+ flags &= ~FLAG_SHOW_LIGHTS;
+ }
+ if ((flags & FLAG_ONGOING_EVENT) != 0) {
+ flagStrings.add("ONGOING_EVENT");
+ flags &= ~FLAG_ONGOING_EVENT;
+ }
+ if ((flags & FLAG_INSISTENT) != 0) {
+ flagStrings.add("INSISTENT");
+ flags &= ~FLAG_INSISTENT;
+ }
+ if ((flags & FLAG_ONLY_ALERT_ONCE) != 0) {
+ flagStrings.add("ONLY_ALERT_ONCE");
+ flags &= ~FLAG_ONLY_ALERT_ONCE;
+ }
+ if ((flags & FLAG_AUTO_CANCEL) != 0) {
+ flagStrings.add("AUTO_CANCEL");
+ flags &= ~FLAG_AUTO_CANCEL;
+ }
+ if ((flags & FLAG_NO_CLEAR) != 0) {
+ flagStrings.add("NO_CLEAR");
+ flags &= ~FLAG_NO_CLEAR;
+ }
+ if ((flags & FLAG_FOREGROUND_SERVICE) != 0) {
+ flagStrings.add("FOREGROUND_SERVICE");
+ flags &= ~FLAG_FOREGROUND_SERVICE;
+ }
+ if ((flags & FLAG_HIGH_PRIORITY) != 0) {
+ flagStrings.add("HIGH_PRIORITY");
+ flags &= ~FLAG_HIGH_PRIORITY;
+ }
+ if ((flags & FLAG_LOCAL_ONLY) != 0) {
+ flagStrings.add("LOCAL_ONLY");
+ flags &= ~FLAG_LOCAL_ONLY;
+ }
+ if ((flags & FLAG_GROUP_SUMMARY) != 0) {
+ flagStrings.add("GROUP_SUMMARY");
+ flags &= ~FLAG_GROUP_SUMMARY;
+ }
+ if ((flags & FLAG_AUTOGROUP_SUMMARY) != 0) {
+ flagStrings.add("AUTOGROUP_SUMMARY");
+ flags &= ~FLAG_AUTOGROUP_SUMMARY;
+ }
+ if ((flags & FLAG_CAN_COLORIZE) != 0) {
+ flagStrings.add("CAN_COLORIZE");
+ flags &= ~FLAG_CAN_COLORIZE;
+ }
+ if ((flags & FLAG_BUBBLE) != 0) {
+ flagStrings.add("BUBBLE");
+ flags &= ~FLAG_BUBBLE;
+ }
+ if ((flags & FLAG_NO_DISMISS) != 0) {
+ flagStrings.add("NO_DISMISS");
+ flags &= ~FLAG_NO_DISMISS;
+ }
+ if ((flags & FLAG_FSI_REQUESTED_BUT_DENIED) != 0) {
+ flagStrings.add("FSI_REQUESTED_BUT_DENIED");
+ flags &= ~FLAG_FSI_REQUESTED_BUT_DENIED;
+ }
+ if ((flags & FLAG_USER_INITIATED_JOB) != 0) {
+ flagStrings.add("USER_INITIATED_JOB");
+ flags &= ~FLAG_USER_INITIATED_JOB;
+ }
+ if (Flags.lifetimeExtensionRefactor()) {
+ if ((flags & FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY) != 0) {
+ flagStrings.add("LIFETIME_EXTENDED_BY_DIRECT_REPLY");
+ flags &= ~FLAG_LIFETIME_EXTENDED_BY_DIRECT_REPLY;
+ }
+ }
+
+ if (flagStrings.isEmpty()) {
+ return "0";
+ }
+
+ if (flags != 0) {
+ flagStrings.add(String.format("UNKNOWN(0x%08x)", flags));
+ }
+
+ return String.join("|", flagStrings);
+ }
+
+ /** @hide */
+ public static String defaultsToString(int defaults) {
+ final List<String> defaultStrings = new ArrayList<String>();
+ if ((defaults & DEFAULT_ALL) == DEFAULT_ALL) {
+ defaultStrings.add("ALL");
+ defaults &= ~DEFAULT_ALL;
+ }
+ if ((defaults & DEFAULT_SOUND) != 0) {
+ defaultStrings.add("SOUND");
+ defaults &= ~DEFAULT_SOUND;
+ }
+ if ((defaults & DEFAULT_VIBRATE) != 0) {
+ defaultStrings.add("VIBRATE");
+ defaults &= ~DEFAULT_VIBRATE;
+ }
+ if ((defaults & DEFAULT_LIGHTS) != 0) {
+ defaultStrings.add("LIGHTS");
+ defaults &= ~DEFAULT_LIGHTS;
+ }
+
+ if (defaultStrings.isEmpty()) {
+ return "0";
+ }
+
+ if (defaults != 0) {
+ defaultStrings.add(String.format("UNKNOWN(0x%08x)", defaults));
+ }
+
+ return String.join("|", defaultStrings);
+ }
+
+ /**
* @hide
*/
public boolean hasCompletedProgress() {
@@ -8154,9 +8285,6 @@
*/
public BigTextStyle bigText(CharSequence cs) {
mBigText = safeCharSequence(cs);
- if (Flags.cleanUpSpansAndNewLines()) {
- mBigText = cleanUpNewLines(mBigText);
- }
return this;
}
@@ -8227,6 +8355,9 @@
// Replace the text with the big text, but only if the big text is not empty.
CharSequence bigTextText = mBuilder.processLegacyText(mBigText);
+ if (Flags.cleanUpSpansAndNewLines()) {
+ bigTextText = cleanUpNewLines(stripStyling(bigTextText));
+ }
if (!TextUtils.isEmpty(bigTextText)) {
p.text(bigTextText);
}
@@ -9142,11 +9273,43 @@
*/
public void ensureColorContrastOrStripStyling(int backgroundColor) {
if (Flags.cleanUpSpansAndNewLines()) {
- mText = stripStyling(mText);
+ mText = stripNonStyleSpans(mText);
} else {
ensureColorContrast(backgroundColor);
}
}
+
+ private CharSequence stripNonStyleSpans(CharSequence text) {
+
+ if (text instanceof Spanned) {
+ Spanned ss = (Spanned) text;
+ Object[] spans = ss.getSpans(0, ss.length(), Object.class);
+ SpannableStringBuilder builder = new SpannableStringBuilder(ss.toString());
+ for (Object span : spans) {
+ final Object resultSpan;
+ if (span instanceof StyleSpan
+ || span instanceof StrikethroughSpan
+ || span instanceof UnderlineSpan) {
+ resultSpan = span;
+ } else if (span instanceof TextAppearanceSpan) {
+ final TextAppearanceSpan originalSpan = (TextAppearanceSpan) span;
+ resultSpan = new TextAppearanceSpan(
+ null,
+ originalSpan.getTextStyle(),
+ -1,
+ null,
+ null);
+ } else {
+ continue;
+ }
+ builder.setSpan(resultSpan, ss.getSpanStart(span), ss.getSpanEnd(span),
+ ss.getSpanFlags(span));
+ }
+ return builder;
+ }
+ return text;
+ }
+
/**
* Updates TextAppearance spans in the message text so it has sufficient contrast
* against its background.
diff --git a/core/java/android/app/contextualsearch/ContextualSearchManager.java b/core/java/android/app/contextualsearch/ContextualSearchManager.java
index c080a6b..cfbe741 100644
--- a/core/java/android/app/contextualsearch/ContextualSearchManager.java
+++ b/core/java/android/app/contextualsearch/ContextualSearchManager.java
@@ -27,6 +27,7 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.util.Log;
import java.lang.annotation.Retention;
@@ -51,6 +52,7 @@
*/
public static final String EXTRA_ENTRYPOINT =
"android.app.contextualsearch.extra.ENTRYPOINT";
+
/**
* Key to get the flag_secure value from the extras of the activity launched by contextual
* search. The value will be true if flag_secure is found in any of the visible activities.
@@ -58,12 +60,14 @@
*/
public static final String EXTRA_FLAG_SECURE_FOUND =
"android.app.contextualsearch.extra.FLAG_SECURE_FOUND";
+
/**
* Key to get the screenshot from the extras of the activity launched by contextual search.
* Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH.
*/
public static final String EXTRA_SCREENSHOT =
"android.app.contextualsearch.extra.SCREENSHOT";
+
/**
* Key to check whether managed profile is visible from the extras of the activity launched by
* contextual search. The value will be true if any one of the visible apps is managed.
@@ -71,6 +75,7 @@
*/
public static final String EXTRA_IS_MANAGED_PROFILE_VISIBLE =
"android.app.contextualsearch.extra.IS_MANAGED_PROFILE_VISIBLE";
+
/**
* Key to get the list of visible packages from the extras of the activity launched by
* contextual search.
@@ -80,6 +85,18 @@
"android.app.contextualsearch.extra.VISIBLE_PACKAGE_NAMES";
/**
+ * Key to get the time the user made the invocation request, based on
+ * {@link SystemClock#uptimeMillis()}.
+ * Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH.
+ *
+ * TODO: un-hide in W
+ *
+ * @hide
+ */
+ public static final String EXTRA_INVOCATION_TIME_MS =
+ "android.app.contextualsearch.extra.INVOCATION_TIME_MS";
+
+ /**
* Key to get the binder token from the extras of the activity launched by contextual search.
* This token is needed to invoke {@link CallbackToken#getContextualSearchState} method.
* Only supposed to be used with ACTON_LAUNCH_CONTEXTUAL_SEARCH.
diff --git a/core/java/android/app/servertransaction/ClientTransactionListenerController.java b/core/java/android/app/servertransaction/ClientTransactionListenerController.java
index c9b4aa1..cda2867 100644
--- a/core/java/android/app/servertransaction/ClientTransactionListenerController.java
+++ b/core/java/android/app/servertransaction/ClientTransactionListenerController.java
@@ -17,14 +17,13 @@
package android.app.servertransaction;
import static android.app.WindowConfiguration.areConfigurationsEqualForDisplay;
+import static android.view.Display.INVALID_DISPLAY;
import static com.android.window.flags.Flags.activityWindowInfoFlag;
import static com.android.window.flags.Flags.bundleClientTransactionFlag;
import static java.util.Objects.requireNonNull;
-import android.annotation.AnyThread;
-import android.annotation.MainThread;
import android.annotation.NonNull;
import android.app.Activity;
import android.app.ActivityThread;
@@ -62,9 +61,11 @@
* Keeps track of the Context whose Configuration will get updated, mapping to the config before
* the change.
*/
+ @GuardedBy("mLock")
private final ArrayMap<Context, Configuration> mContextToPreChangedConfigMap = new ArrayMap<>();
/** Whether there is an {@link ClientTransaction} being executed. */
+ @GuardedBy("mLock")
private boolean mIsClientTransactionExecuting;
/** Gets the singleton controller. */
@@ -96,7 +97,6 @@
* The listener will be invoked with two parameters: {@link Activity#getActivityToken()} and
* {@link ActivityWindowInfo}.
*/
- @AnyThread
public void registerActivityWindowInfoChangedListener(
@NonNull BiConsumer<IBinder, ActivityWindowInfo> listener) {
if (!activityWindowInfoFlag()) {
@@ -111,7 +111,6 @@
* Unregisters the listener that was previously registered via
* {@link #registerActivityWindowInfoChangedListener(BiConsumer)}
*/
- @AnyThread
public void unregisterActivityWindowInfoChangedListener(
@NonNull BiConsumer<IBinder, ActivityWindowInfo> listener) {
if (!activityWindowInfoFlag()) {
@@ -126,7 +125,6 @@
* Called when receives a {@link ClientTransaction} that is updating an activity's
* {@link ActivityWindowInfo}.
*/
- @MainThread
public void onActivityWindowInfoChanged(@NonNull IBinder activityToken,
@NonNull ActivityWindowInfo activityWindowInfo) {
if (!activityWindowInfoFlag()) {
@@ -146,80 +144,85 @@
}
/** Called when starts executing a remote {@link ClientTransaction}. */
- @MainThread
public void onClientTransactionStarted() {
- mIsClientTransactionExecuting = true;
+ synchronized (mLock) {
+ mIsClientTransactionExecuting = true;
+ }
}
/** Called when finishes executing a remote {@link ClientTransaction}. */
- @MainThread
public void onClientTransactionFinished() {
- notifyDisplayManagerIfNeeded();
- mIsClientTransactionExecuting = false;
+ final ArraySet<Integer> configUpdatedDisplayIds;
+ synchronized (mLock) {
+ mIsClientTransactionExecuting = false;
+
+ // When {@link Configuration} is changed, we want to trigger display change callback as
+ // well, because Display reads some fields from {@link Configuration}.
+ if (mContextToPreChangedConfigMap.isEmpty()) {
+ return;
+ }
+
+ // Calculate display ids that have config changed.
+ configUpdatedDisplayIds = new ArraySet<>();
+ final int contextCount = mContextToPreChangedConfigMap.size();
+ try {
+ for (int i = 0; i < contextCount; i++) {
+ final Context context = mContextToPreChangedConfigMap.keyAt(i);
+ final Configuration preChangedConfig = mContextToPreChangedConfigMap.valueAt(i);
+ if (shouldReportDisplayChange(context, preChangedConfig)) {
+ configUpdatedDisplayIds.add(context.getDisplayId());
+ }
+ }
+ } finally {
+ mContextToPreChangedConfigMap.clear();
+ }
+ }
+
+ // Dispatch the display changed callbacks.
+ final int displayCount = configUpdatedDisplayIds.size();
+ for (int i = 0; i < displayCount; i++) {
+ final int displayId = configUpdatedDisplayIds.valueAt(i);
+ onDisplayChanged(displayId);
+ }
}
/** Called before updating the Configuration of the given {@code context}. */
- @MainThread
public void onContextConfigurationPreChanged(@NonNull Context context) {
if (!bundleClientTransactionFlag() || ActivityThread.isSystem()) {
// Not enable for system server.
return;
}
- if (mContextToPreChangedConfigMap.containsKey(context)) {
- // There is an earlier change that hasn't been reported yet.
- return;
+ synchronized (mLock) {
+ if (mContextToPreChangedConfigMap.containsKey(context)) {
+ // There is an earlier change that hasn't been reported yet.
+ return;
+ }
+ mContextToPreChangedConfigMap.put(context,
+ new Configuration(context.getResources().getConfiguration()));
}
- mContextToPreChangedConfigMap.put(context,
- new Configuration(context.getResources().getConfiguration()));
}
/** Called after updating the Configuration of the given {@code context}. */
- @MainThread
public void onContextConfigurationPostChanged(@NonNull Context context) {
if (!bundleClientTransactionFlag() || ActivityThread.isSystem()) {
// Not enable for system server.
return;
}
- if (mIsClientTransactionExecuting) {
- // Wait until #onClientTransactionFinished to prevent it from triggering the same
- // #onDisplayChanged multiple times within the same ClientTransaction.
- return;
- }
- final Configuration preChangedConfig = mContextToPreChangedConfigMap.remove(context);
- if (preChangedConfig != null && shouldReportDisplayChange(context, preChangedConfig)) {
- onDisplayChanged(context.getDisplayId());
- }
- }
-
- /**
- * When {@link Configuration} is changed, we want to trigger display change callback as well,
- * because Display reads some fields from {@link Configuration}.
- */
- private void notifyDisplayManagerIfNeeded() {
- if (mContextToPreChangedConfigMap.isEmpty()) {
- return;
- }
- // Whether the configuration change should trigger DisplayListener#onDisplayChanged.
- try {
- // Calculate display ids that have config changed.
- final ArraySet<Integer> configUpdatedDisplayIds = new ArraySet<>();
- final int contextCount = mContextToPreChangedConfigMap.size();
- for (int i = 0; i < contextCount; i++) {
- final Context context = mContextToPreChangedConfigMap.keyAt(i);
- final Configuration preChangedConfig = mContextToPreChangedConfigMap.valueAt(i);
- if (shouldReportDisplayChange(context, preChangedConfig)) {
- configUpdatedDisplayIds.add(context.getDisplayId());
- }
+ int changedDisplayId = INVALID_DISPLAY;
+ synchronized (mLock) {
+ if (mIsClientTransactionExecuting) {
+ // Wait until #onClientTransactionFinished to prevent it from triggering the same
+ // #onDisplayChanged multiple times within the same ClientTransaction.
+ return;
}
-
- // Dispatch the display changed callbacks.
- final int displayCount = configUpdatedDisplayIds.size();
- for (int i = 0; i < displayCount; i++) {
- final int displayId = configUpdatedDisplayIds.valueAt(i);
- onDisplayChanged(displayId);
+ final Configuration preChangedConfig = mContextToPreChangedConfigMap.remove(context);
+ if (preChangedConfig != null && shouldReportDisplayChange(context, preChangedConfig)) {
+ changedDisplayId = context.getDisplayId();
}
- } finally {
- mContextToPreChangedConfigMap.clear();
+ }
+
+ if (changedDisplayId != INVALID_DISPLAY) {
+ onDisplayChanged(changedDisplayId);
}
}
diff --git a/core/java/android/companion/virtual/camera/VirtualCameraConfig.java b/core/java/android/companion/virtual/camera/VirtualCameraConfig.java
index 06a0f5c..769b658 100644
--- a/core/java/android/companion/virtual/camera/VirtualCameraConfig.java
+++ b/core/java/android/companion/virtual/camera/VirtualCameraConfig.java
@@ -237,19 +237,15 @@
@IntRange(from = 1) int height,
@ImageFormat.Format int format,
@IntRange(from = 1) int maximumFramesPerSecond) {
- // TODO(b/310857519): Check dimension upper limits based on the maximum texture size
- // supported by the current device, instead of hardcoded limits.
- if (width <= 0 || width > VirtualCameraStreamConfig.DIMENSION_UPPER_LIMIT) {
+ if (width <= 0) {
throw new IllegalArgumentException(
"Invalid width passed for stream config: " + width
- + ", must be between 1 and "
- + VirtualCameraStreamConfig.DIMENSION_UPPER_LIMIT);
+ + ", must be greater than 0");
}
- if (height <= 0 || height > VirtualCameraStreamConfig.DIMENSION_UPPER_LIMIT) {
+ if (height <= 0) {
throw new IllegalArgumentException(
"Invalid height passed for stream config: " + height
- + ", must be between 1 and "
- + VirtualCameraStreamConfig.DIMENSION_UPPER_LIMIT);
+ + ", must be greater than 0");
}
if (!isFormatSupported(format)) {
throw new IllegalArgumentException(
diff --git a/core/java/android/companion/virtual/camera/VirtualCameraStreamConfig.java b/core/java/android/companion/virtual/camera/VirtualCameraStreamConfig.java
index 00a814e..6ab66b3 100644
--- a/core/java/android/companion/virtual/camera/VirtualCameraStreamConfig.java
+++ b/core/java/android/companion/virtual/camera/VirtualCameraStreamConfig.java
@@ -39,11 +39,6 @@
public final class VirtualCameraStreamConfig implements Parcelable {
// TODO(b/310857519): Check if we should increase the fps upper limit in future.
static final int MAX_FPS_UPPER_LIMIT = 60;
- // This is the minimum guaranteed upper bound of texture size supported by all devices.
- // Keep this in sync with kMaxTextureSize from services/camera/virtualcamera/util/Util.cc
- // TODO(b/310857519): Remove this once we add support for fetching the maximum texture size
- // supported by the current device.
- static final int DIMENSION_UPPER_LIMIT = 2048;
private final int mWidth;
private final int mHeight;
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 535cebb..7ac9547 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1548,6 +1548,26 @@
public static final long INSETS_DECOUPLED_CONFIGURATION_ENFORCED = 151861875L;
/**
+ * When enabled, the activity will receive configuration decoupled from system bar insets.
+ *
+ * <p>This will only apply if the activity is targeting SDK level 34 or earlier versions.
+ *
+ * <p>This will only in effect if the device is trying to provide a different value by default
+ * other than the legacy value, i.e., the
+ * {@code Flags.allowsScreenSizeDecoupledFromStatusBarAndCutout()} is set to true.
+ *
+ * <p>If the {@code Flags.insetsDecoupledConfiguration()} is also set to true, all apps
+ * targeting SDK level 35 or later, and apps with this override flag will receive the insets
+ * decoupled configuration.
+ *
+ * @hide
+ */
+ @ChangeId
+ @Disabled
+ @Overridable
+ public static final long OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION = 327313645L;
+
+ /**
* Optional set of a certificates identifying apps that are allowed to embed this activity. From
* the "knownActivityEmbeddingCerts" attribute.
*/
diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig
index 6d3a56d..c57a3a6 100644
--- a/core/java/android/content/pm/multiuser.aconfig
+++ b/core/java/android/content/pm/multiuser.aconfig
@@ -113,6 +113,26 @@
is_fixed_read_only: true
}
+flag {
+ name: "fix_avatar_picker_read_back_order"
+ namespace: "multiuser"
+ description: "Talkback focus doesn't move to the 'If you change your Google Account picture…' after swiping next to move the focus from 'Choose a picture'"
+ bug: "330835921"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "fix_avatar_picker_selected_read_back"
+ namespace: "multiuser"
+ description: "Talkback doesn't announce 'selected' after double tapping the button in the picture list in 'Choose a picture' page."
+ bug: "330840549"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
# This flag guards the private space feature and all its implementations excluding the APIs. APIs are guarded by android.os.Flags.allow_private_profile.
flag {
name: "enable_private_space_features"
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 2081ced..3c4307c 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -22,6 +22,7 @@
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
+import android.database.sqlite.Flags;
import android.database.sqlite.SQLiteAbortException;
import android.database.sqlite.SQLiteConstraintException;
import android.database.sqlite.SQLiteDatabase;
@@ -1609,7 +1610,7 @@
* Comments either start with "--" and run to the end of the line or are C-style block
* comments. The function returns null if a prefix could not be found.
*/
- private static String getSqlStatementPrefixExtended(String sql) {
+ private static String getSqlStatementPrefixExtendedRegex(String sql) {
Matcher m = sPrefixPattern.matcher(sql);
if (m.lookingAt()) {
return m.group(PREFIX_GROUP_NUM).toUpperCase(Locale.ROOT);
@@ -1619,6 +1620,61 @@
}
/**
+ * Return the index of the first character past comments and whitespace. -1 is returned if
+ * a comment is malformed.
+ */
+ private static int getSqlStatementPrefixOffset(String s) {
+ final int limit = s.length() - 2;
+ if (limit < 0) return -1;
+ int i = 0;
+ while (i < limit) {
+ final char c = s.charAt(i);
+ if (c <= ' ') {
+ // This behavior conforms to String.trim(), which is used by the legacy Android
+ // SQL prefix logic. This test is not unicode-aware. Notice that it accepts the
+ // null character as whitespace even though the null character will terminate the
+ // SQL string in native code.
+ i++;
+ } else if (c == '-') {
+ if (s.charAt(i+1) != '-') return i;
+ i = s.indexOf('\n', i+2);
+ if (i < 0) return -1;
+ i++;
+ } else if (c == '/') {
+ if (s.charAt(i+1) != '*') return i;
+ i++;
+ do {
+ i = s.indexOf('*', i+1);
+ if (i < 0) return -1;
+ i++;
+ } while (s.charAt(i) != '/');
+ i++;
+ } else {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Scan past leading comments without using the Java regex routines.
+ */
+ private static String getSqlStatementPrefixExtendedNoRegex(String sql) {
+ int n = getSqlStatementPrefixOffset(sql);
+ if (n < 0) {
+ // Bad comment syntax.
+ return null;
+ }
+ final int end = sql.length();
+ if (n > end) {
+ // Bad scanning. This indicates a programming error.
+ return null;
+ }
+ final int eos = Math.min(n+3, end);
+ return sql.substring(n, eos).toUpperCase(Locale.ROOT);
+ }
+
+ /**
* Return the extended statement type for the SQL statement. This is not a public API and it
* can return values that are not publicly visible.
* @hide
@@ -1663,11 +1719,15 @@
* @hide
*/
public static int getSqlStatementTypeExtended(@NonNull String sql) {
- int type = categorizeStatement(getSqlStatementPrefixSimple(sql), sql);
- if (type == STATEMENT_COMMENT) {
- type = categorizeStatement(getSqlStatementPrefixExtended(sql), sql);
+ if (Flags.simpleSqlCommentScanner()) {
+ return categorizeStatement(getSqlStatementPrefixExtendedNoRegex(sql), sql);
+ } else {
+ int type = categorizeStatement(getSqlStatementPrefixSimple(sql), sql);
+ if (type == STATEMENT_COMMENT) {
+ type = categorizeStatement(getSqlStatementPrefixExtendedRegex(sql), sql);
+ }
+ return type;
}
- return type;
}
/**
diff --git a/core/java/android/database/sqlite/flags.aconfig b/core/java/android/database/sqlite/flags.aconfig
index 3073e25..285f984 100644
--- a/core/java/android/database/sqlite/flags.aconfig
+++ b/core/java/android/database/sqlite/flags.aconfig
@@ -17,3 +17,11 @@
description: "Permit updates to TEMP tables in read-only transactions"
bug: "317993835"
}
+
+flag {
+ name: "simple_sql_comment_scanner"
+ namespace: "system_performance"
+ is_fixed_read_only: true
+ description: "Scan SQL comments by hand instead of with a regex"
+ bug: "329118560"
+}
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 735b20f..c82e7e8 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1494,7 +1494,7 @@
* {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration}.</p>
* <p>Note that the actual achievable max framerate also depends on the minimum frame
* duration of the output streams. The max frame rate will be
- * <code>min(aeTargetFpsRange.maxFps, 1 / max(individual stream min durations)</code>. For example,
+ * <code>min(aeTargetFpsRange.maxFps, 1 / max(individual stream min durations))</code>. For example,
* if the application sets this key to <code>{60, 60}</code>, but the maximum minFrameDuration among
* all configured streams is 33ms, the maximum framerate won't be 60fps, but will be
* 30fps.</p>
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 76287ca..5765a73 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -893,7 +893,7 @@
* {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration}.</p>
* <p>Note that the actual achievable max framerate also depends on the minimum frame
* duration of the output streams. The max frame rate will be
- * <code>min(aeTargetFpsRange.maxFps, 1 / max(individual stream min durations)</code>. For example,
+ * <code>min(aeTargetFpsRange.maxFps, 1 / max(individual stream min durations))</code>. For example,
* if the application sets this key to <code>{60, 60}</code>, but the maximum minFrameDuration among
* all configured streams is 33ms, the maximum framerate won't be 60fps, but will be
* 30fps.</p>
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 37f2fb2..25bfb2a 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -962,24 +962,6 @@
}
}
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- /**
- * @hide
- */
- @RequiresPermission(USE_BIOMETRIC_INTERNAL)
- public void setSidefpsController(@NonNull ISidefpsController controller) {
- if (mService == null) {
- Slog.w(TAG, "setSidefpsController: no fingerprint service");
- return;
- }
-
- try {
- mService.setSidefpsController(controller);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
/**
* Forwards BiometricStateListener to FingerprintService
* @param listener new BiometricStateListener being added
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 6a96ac4..742fa57 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -27,7 +27,6 @@
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
import android.hardware.fingerprint.IUdfpsOverlayController;
-import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintEnrollOptions;
@@ -200,10 +199,6 @@
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
void setUdfpsOverlayController(in IUdfpsOverlayController controller);
- // Sets the controller for managing the SideFPS overlay.
- @EnforcePermission("USE_BIOMETRIC_INTERNAL")
- void setSidefpsController(in ISidefpsController controller);
-
// Registers AuthenticationStateListener.
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
void registerAuthenticationStateListener(AuthenticationStateListener listener);
diff --git a/core/java/android/hardware/fingerprint/ISidefpsController.aidl b/core/java/android/hardware/fingerprint/ISidefpsController.aidl
deleted file mode 100644
index 684f18f..0000000
--- a/core/java/android/hardware/fingerprint/ISidefpsController.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2021 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 android.hardware.fingerprint;
-
-/**
- * Interface for interacting with the side fingerprint sensor (side-fps) overlay.
- * @hide
- */
-oneway interface ISidefpsController {
-
- // Shows the overlay for the given sensor with a reason from BiometricOverlayConstants.
- void show(int sensorId, int reason);
-
- // Hides the overlay.
- void hide(int sensorId);
-}
diff --git a/core/java/android/os/connectivity/WifiActivityEnergyInfo.java b/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
index ad74a9f..2ceb1c7 100644
--- a/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
+++ b/core/java/android/os/connectivity/WifiActivityEnergyInfo.java
@@ -37,8 +37,10 @@
* real-time.
* @hide
*/
+@android.ravenwood.annotation.RavenwoodKeepWholeClass
@SystemApi
public final class WifiActivityEnergyInfo implements Parcelable {
+ private static final long DEFERRED_ENERGY_ESTIMATE = -1;
@ElapsedRealtimeLong
private final long mTimeSinceBootMillis;
@StackState
@@ -52,7 +54,7 @@
@IntRange(from = 0)
private final long mControllerIdleDurationMillis;
@IntRange(from = 0)
- private final long mControllerEnergyUsedMicroJoules;
+ private long mControllerEnergyUsedMicroJoules;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -99,9 +101,10 @@
rxDurationMillis,
scanDurationMillis,
idleDurationMillis,
- calculateEnergyMicroJoules(txDurationMillis, rxDurationMillis, idleDurationMillis));
+ DEFERRED_ENERGY_ESTIMATE);
}
+ @android.ravenwood.annotation.RavenwoodReplace
private static long calculateEnergyMicroJoules(
long txDurationMillis, long rxDurationMillis, long idleDurationMillis) {
final Context context = ActivityThread.currentActivityThread().getSystemContext();
@@ -125,6 +128,11 @@
* voltage);
}
+ private static long calculateEnergyMicroJoules$ravenwood(long txDurationMillis,
+ long rxDurationMillis, long idleDurationMillis) {
+ return 0;
+ }
+
/** @hide */
public WifiActivityEnergyInfo(
@ElapsedRealtimeLong long timeSinceBootMillis,
@@ -152,7 +160,7 @@
+ " mControllerRxDurationMillis=" + mControllerRxDurationMillis
+ " mControllerScanDurationMillis=" + mControllerScanDurationMillis
+ " mControllerIdleDurationMillis=" + mControllerIdleDurationMillis
- + " mControllerEnergyUsedMicroJoules=" + mControllerEnergyUsedMicroJoules
+ + " mControllerEnergyUsedMicroJoules=" + getControllerEnergyUsedMicroJoules()
+ " }";
}
@@ -231,6 +239,11 @@
/** Get the energy consumed by Wifi, in microjoules. */
@IntRange(from = 0)
public long getControllerEnergyUsedMicroJoules() {
+ if (mControllerEnergyUsedMicroJoules == DEFERRED_ENERGY_ESTIMATE) {
+ mControllerEnergyUsedMicroJoules = calculateEnergyMicroJoules(
+ mControllerTxDurationMillis, mControllerRxDurationMillis,
+ mControllerIdleDurationMillis);
+ }
return mControllerEnergyUsedMicroJoules;
}
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 3b59901..55011e5 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -98,7 +98,7 @@
IBinder registerAttributionSource(in AttributionSourceState source);
- int getNumRegisteredAttributionSources(int uid);
+ int getRegisteredAttributionSourceCount(int uid);
boolean isRegisteredAttributionSource(in AttributionSourceState source);
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 2daf4ac..55bb430 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -1680,9 +1680,9 @@
* @hide
*/
@RequiresPermission(Manifest.permission.UPDATE_APP_OPS_STATS)
- public int getNumRegisteredAttributionSourcesForTest(int uid) {
+ public int getRegisteredAttributionSourceCountForTest(int uid) {
try {
- return mPermissionManager.getNumRegisteredAttributionSources(uid);
+ return mPermissionManager.getRegisteredAttributionSourceCount(uid);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
diff --git a/core/java/android/service/dreams/DreamOverlayService.java b/core/java/android/service/dreams/DreamOverlayService.java
index 9a02b74b..5da0cb4 100644
--- a/core/java/android/service/dreams/DreamOverlayService.java
+++ b/core/java/android/service/dreams/DreamOverlayService.java
@@ -79,6 +79,11 @@
mService.endDream(this);
}
+ @Override
+ public void comeToFront() {
+ mService.comeToFront(this);
+ }
+
private void onExitRequested() {
try {
mDreamOverlayCallback.onExitRequested();
@@ -130,6 +135,16 @@
});
}
+ private void comeToFront(OverlayClient client) {
+ mExecutor.execute(() -> {
+ if (mCurrentClient != client) {
+ return;
+ }
+
+ onComeToFront();
+ });
+ }
+
private IDreamOverlay mDreamOverlay = new IDreamOverlay.Stub() {
@Override
public void getClient(IDreamOverlayClientCallback callback) {
@@ -190,6 +205,13 @@
public void onWakeUp() {}
/**
+ * This method is overridden by implementations to handle when the dream is coming to the front
+ * (after having lost focus to something on top of it).
+ * @hide
+ */
+ public void onComeToFront() {}
+
+ /**
* This method is overridden by implementations to handle when the dream has ended. There may
* be earlier signals leading up to this step, such as @{@link #onWakeUp(Runnable)}.
*
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 353828c..c26d83c 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -18,6 +18,7 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.service.dreams.Flags.dreamHandlesConfirmKeys;
+import static android.service.dreams.Flags.dreamTracksFocus;
import android.annotation.FlaggedApi;
import android.annotation.IdRes;
@@ -52,6 +53,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.service.controls.flags.Flags;
+import android.service.dreams.utils.DreamAccessibility;
import android.util.AttributeSet;
import android.util.Log;
import android.util.MathUtils;
@@ -273,6 +275,7 @@
private boolean mDebug = false;
private ComponentName mDreamComponent;
+ private DreamAccessibility mDreamAccessibility;
private boolean mShouldShowComplications;
private DreamServiceWrapper mDreamServiceWrapper;
@@ -455,6 +458,15 @@
/** {@inheritDoc} */
@Override
public void onWindowFocusChanged(boolean hasFocus) {
+ if (!dreamTracksFocus()) {
+ return;
+ }
+
+ try {
+ mDreamManager.onDreamFocusChanged(hasFocus);
+ } catch (RemoteException ex) {
+ // system server died
+ }
}
/** {@inheritDoc} */
@@ -664,6 +676,7 @@
*/
public void setInteractive(boolean interactive) {
mInteractive = interactive;
+ updateAccessibilityMessage();
}
/**
@@ -1149,6 +1162,19 @@
wakeUp(false);
}
+ /**
+ * Tells the dream to come to the front (which in turn tells the overlay to come to the front).
+ */
+ private void comeToFront() {
+ mOverlayConnection.addConsumer(overlay -> {
+ try {
+ overlay.comeToFront();
+ } catch (RemoteException e) {
+ Log.e(mTag, "could not tell overlay to come to front:" + e);
+ }
+ });
+ }
+
private void wakeUp(boolean fromSystem) {
if (mDebug) {
Slog.v(mTag, "wakeUp(): fromSystem=" + fromSystem + ", mWaking=" + mWaking
@@ -1430,7 +1456,7 @@
// Hide all insets when the dream is showing
mWindow.getDecorView().getWindowInsetsController().hide(WindowInsets.Type.systemBars());
mWindow.setDecorFitsSystemWindows(false);
-
+ updateAccessibilityMessage();
mWindow.getDecorView().addOnAttachStateChangeListener(
new View.OnAttachStateChangeListener() {
private Consumer<IDreamOverlayClient> mDreamStartOverlayConsumer;
@@ -1477,6 +1503,15 @@
});
}
+ private void updateAccessibilityMessage() {
+ if (mWindow == null) return;
+ if (mDreamAccessibility == null) {
+ final View rootView = mWindow.getDecorView();
+ mDreamAccessibility = new DreamAccessibility(this, rootView);
+ }
+ mDreamAccessibility.updateAccessibilityConfiguration(isInteractive());
+ }
+
private boolean getWindowFlagValue(int flag, boolean defaultValue) {
return mWindow == null ? defaultValue : (mWindow.getAttributes().flags & flag) != 0;
}
@@ -1596,6 +1631,15 @@
public void wakeUp() {
mHandler.post(() -> DreamService.this.wakeUp(true /*fromSystem*/));
}
+
+ @Override
+ public void comeToFront() {
+ if (!dreamTracksFocus()) {
+ return;
+ }
+
+ mHandler.post(DreamService.this::comeToFront);
+ }
}
/** @hide */
diff --git a/core/java/android/service/dreams/IDreamManager.aidl b/core/java/android/service/dreams/IDreamManager.aidl
index e45384f..85f0368 100644
--- a/core/java/android/service/dreams/IDreamManager.aidl
+++ b/core/java/android/service/dreams/IDreamManager.aidl
@@ -48,4 +48,5 @@
void setSystemDreamComponent(in ComponentName componentName);
void registerDreamOverlayService(in ComponentName componentName);
void startDreamActivity(in Intent intent);
+ void onDreamFocusChanged(in boolean hasFocus);
}
diff --git a/core/java/android/service/dreams/IDreamOverlayClient.aidl b/core/java/android/service/dreams/IDreamOverlayClient.aidl
index 78b7280..5054d4d 100644
--- a/core/java/android/service/dreams/IDreamOverlayClient.aidl
+++ b/core/java/android/service/dreams/IDreamOverlayClient.aidl
@@ -42,4 +42,7 @@
/** Called when the dream has ended. */
void endDream();
+
+ /** Called when the dream is coming to the front. */
+ void comeToFront();
}
diff --git a/core/java/android/service/dreams/IDreamService.aidl b/core/java/android/service/dreams/IDreamService.aidl
index 8b5d875..2e2651b 100644
--- a/core/java/android/service/dreams/IDreamService.aidl
+++ b/core/java/android/service/dreams/IDreamService.aidl
@@ -25,4 +25,5 @@
void attach(IBinder windowToken, boolean canDoze, boolean isPreviewMode, IRemoteCallback started);
void detach();
void wakeUp();
+ void comeToFront();
}
diff --git a/core/java/android/service/dreams/flags.aconfig b/core/java/android/service/dreams/flags.aconfig
index 88f1090..0a458bc 100644
--- a/core/java/android/service/dreams/flags.aconfig
+++ b/core/java/android/service/dreams/flags.aconfig
@@ -19,3 +19,10 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "dream_tracks_focus"
+ namespace: "communal"
+ description: "This flag enables the ability for dreams to track whether or not they have focus"
+ bug: "331798001"
+}
diff --git a/core/java/android/service/dreams/utils/DreamAccessibility.java b/core/java/android/service/dreams/utils/DreamAccessibility.java
new file mode 100644
index 0000000..c38f41b
--- /dev/null
+++ b/core/java/android/service/dreams/utils/DreamAccessibility.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2024 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 android.service.dreams.utils;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import com.android.internal.R;
+
+/**
+ * {@link DreamAccessibility} allows customization of accessibility
+ * actions for the root view of the dream overlay.
+ * @hide
+ */
+public class DreamAccessibility {
+ private final Context mContext;
+ private final View mView;
+ private final View.AccessibilityDelegate mAccessibilityDelegate;
+
+ public DreamAccessibility(@NonNull Context context, @NonNull View view) {
+ mContext = context;
+ mView = view;
+ mAccessibilityDelegate = createNewAccessibilityDelegate(mContext);
+ }
+
+ /**
+ * @param interactive
+ * Removes and add accessibility configuration depending if the dream is interactive or not
+ */
+ public void updateAccessibilityConfiguration(Boolean interactive) {
+ if (!interactive) {
+ addAccessibilityConfiguration();
+ } else {
+ removeCustomAccessibilityAction();
+ }
+ }
+
+ /**
+ * Configures the accessibility actions for the given root view.
+ */
+ private void addAccessibilityConfiguration() {
+ mView.setAccessibilityDelegate(mAccessibilityDelegate);
+ }
+
+ /**
+ * Removes Configured the accessibility actions for the given root view.
+ */
+ private void removeCustomAccessibilityAction() {
+ if (mView.getAccessibilityDelegate() == mAccessibilityDelegate) {
+ mView.setAccessibilityDelegate(null);
+ }
+ }
+
+ private View.AccessibilityDelegate createNewAccessibilityDelegate(Context context) {
+ return new View.AccessibilityDelegate() {
+ @Override
+ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ for (AccessibilityNodeInfo.AccessibilityAction action : info.getActionList()) {
+ if (action.getId() == AccessibilityNodeInfo.ACTION_CLICK) {
+ info.removeAction(action);
+ break;
+ }
+ }
+ info.addAction(new AccessibilityNodeInfo.AccessibilityAction(
+ AccessibilityNodeInfo.ACTION_CLICK,
+ context.getResources().getString(R.string.dream_accessibility_action_click)
+ ));
+ }
+ };
+ }
+}
diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java
index 786d768..1d7091c 100644
--- a/core/java/android/service/notification/ZenPolicy.java
+++ b/core/java/android/service/notification/ZenPolicy.java
@@ -349,23 +349,29 @@
/**
* Indicates no explicit setting for which channels may bypass DND when this policy is active.
* Defaults to {@link #CHANNEL_POLICY_PRIORITY}.
+ *
+ * @hide
*/
@FlaggedApi(Flags.FLAG_MODES_API)
- private static final int CHANNEL_POLICY_UNSET = 0;
+ public static final int CHANNEL_POLICY_UNSET = 0;
/**
* Indicates that channels marked as {@link NotificationChannel#canBypassDnd()} can bypass DND
* when this policy is active.
+ *
+ * @hide
*/
@FlaggedApi(Flags.FLAG_MODES_API)
- private static final int CHANNEL_POLICY_PRIORITY = 1;
+ public static final int CHANNEL_POLICY_PRIORITY = 1;
/**
* Indicates that no channels can bypass DND when this policy is active, even those marked as
* {@link NotificationChannel#canBypassDnd()}.
+ *
+ * @hide
*/
@FlaggedApi(Flags.FLAG_MODES_API)
- private static final int CHANNEL_POLICY_NONE = 2;
+ public static final int CHANNEL_POLICY_NONE = 2;
/** @hide */
public ZenPolicy() {
@@ -564,6 +570,13 @@
}
/**
+ * @hide
+ */
+ public @ChannelType int getAllowedChannels() {
+ return mAllowChannels;
+ }
+
+ /**
* Whether this policy allows {@link NotificationChannel channels} marked as
* {@link NotificationChannel#canBypassDnd()} to bypass DND. If {@link #STATE_ALLOW}, these
* channels may bypass; if {@link #STATE_DISALLOW}, then even notifications from channels
@@ -999,6 +1012,12 @@
mZenPolicy.mAllowChannels = allow ? CHANNEL_POLICY_PRIORITY : CHANNEL_POLICY_NONE;
return this;
}
+
+ /** @hide */
+ public @NonNull Builder allowChannels(@ChannelType int channelType) {
+ mZenPolicy.mAllowChannels = channelType;
+ return this;
+ }
}
@Override
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index fb57921..4281da1 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -1685,6 +1685,10 @@
public final void onSimultaneousCallingStateChanged(int[] subIds) {
// not supported on the deprecated interface - Use TelephonyCallback instead
}
+
+ public final void onCarrierRoamingNtnModeChanged(boolean active) {
+ // not supported on the deprecated interface - Use TelephonyCallback instead
+ }
}
private void log(String s) {
diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java
index dc6a035..b8b84d9 100644
--- a/core/java/android/telephony/TelephonyCallback.java
+++ b/core/java/android/telephony/TelephonyCallback.java
@@ -644,6 +644,15 @@
public static final int EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED = 41;
/**
+ * Event for listening to changes in carrier roaming non-terrestrial network mode.
+ *
+ * @see CarrierRoamingNtnModeListener
+ *
+ * @hide
+ */
+ public static final int EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED = 42;
+
+ /**
* @hide
*/
@IntDef(prefix = {"EVENT_"}, value = {
@@ -687,7 +696,8 @@
EVENT_TRIGGER_NOTIFY_ANBR,
EVENT_MEDIA_QUALITY_STATUS_CHANGED,
EVENT_EMERGENCY_CALLBACK_MODE_CHANGED,
- EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED
+ EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED,
+ EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED
})
@Retention(RetentionPolicy.SOURCE)
public @interface TelephonyEvent {
@@ -1686,6 +1696,24 @@
}
/**
+ * Interface for carrier roaming non-terrestrial network listener.
+ *
+ * @hide
+ */
+ public interface CarrierRoamingNtnModeListener {
+ /**
+ * Callback invoked when carrier roaming non-terrestrial network mode changes.
+ *
+ * @param active {@code true} If the device is connected to carrier roaming
+ * non-terrestrial network or was connected within the
+ * {CarrierConfigManager
+ * #KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT} duration,
+ * {code false} otherwise.
+ */
+ void onCarrierRoamingNtnModeChanged(boolean active);
+ }
+
+ /**
* The callback methods need to be called on the handler thread where
* this object was created. If the binder did that for us it'd be nice.
* <p>
@@ -2086,5 +2114,16 @@
Binder.withCleanCallingIdentity(
() -> mExecutor.execute(() -> listener.onCallBackModeStopped(type, reason)));
}
+
+ public void onCarrierRoamingNtnModeChanged(boolean active) {
+ if (!Flags.carrierEnabledSatelliteFlag()) return;
+
+ CarrierRoamingNtnModeListener listener =
+ (CarrierRoamingNtnModeListener) mTelephonyCallbackWeakRef.get();
+ if (listener == null) return;
+
+ Binder.withCleanCallingIdentity(
+ () -> mExecutor.execute(() -> listener.onCarrierRoamingNtnModeChanged(active)));
+ }
}
}
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index d39c4ce..6160fdb 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -1073,6 +1073,24 @@
}
/**
+ * Notify external listeners that carrier roaming non-terrestrial network mode changed.
+ * @param subId subscription ID.
+ * @param active {@code true} If the device is connected to carrier roaming
+ * non-terrestrial network or was connected within the
+ * {CarrierConfigManager#KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT}
+ * duration, {code false} otherwise.
+ * @hide
+ */
+ public void notifyCarrierRoamingNtnModeChanged(int subId, boolean active) {
+ try {
+ sRegistry.notifyCarrierRoamingNtnModeChanged(subId, active);
+ } catch (RemoteException ex) {
+ // system server crash
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Processes potential event changes from the provided {@link TelephonyCallback}.
*
* @param telephonyCallback callback for monitoring callback changes to the telephony state.
@@ -1224,6 +1242,10 @@
eventList.add(
TelephonyCallback.EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED);
}
+
+ if (telephonyCallback instanceof TelephonyCallback.CarrierRoamingNtnModeListener) {
+ eventList.add(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED);
+ }
return eventList;
}
diff --git a/core/java/android/text/MeasuredParagraph.java b/core/java/android/text/MeasuredParagraph.java
index 38aeb37..161a79b 100644
--- a/core/java/android/text/MeasuredParagraph.java
+++ b/core/java/android/text/MeasuredParagraph.java
@@ -30,6 +30,8 @@
import android.graphics.Rect;
import android.graphics.text.LineBreakConfig;
import android.graphics.text.MeasuredText;
+import android.icu.lang.UCharacter;
+import android.icu.lang.UCharacterDirection;
import android.icu.text.Bidi;
import android.text.AutoGrowArray.ByteArray;
import android.text.AutoGrowArray.FloatArray;
@@ -711,7 +713,12 @@
// check the paragraph count here and replace the CR letters and re-calculate
// BiDi again.
for (int i = 0; i < mTextLength; ++i) {
- if (mCopiedBuffer[i] == '\r') {
+ if (Character.isSurrogate(mCopiedBuffer[i])) {
+ // All block separators are in BMP.
+ continue;
+ }
+ if (UCharacter.getDirection(mCopiedBuffer[i])
+ == UCharacterDirection.BLOCK_SEPARATOR) {
mCopiedBuffer[i] = OBJECT_REPLACEMENT_CHARACTER;
}
}
diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java
index bde9c77..3015791 100644
--- a/core/java/android/text/TextLine.java
+++ b/core/java/android/text/TextLine.java
@@ -477,7 +477,12 @@
}
drawBounds.setEmpty();
float w = measure(mLen, false, fmi, drawBounds, lineInfo);
- float boundsWidth = drawBounds.width();
+ float boundsWidth;
+ if (w >= 0) {
+ boundsWidth = Math.max(drawBounds.right, w) - Math.min(0, drawBounds.left);
+ } else {
+ boundsWidth = Math.max(drawBounds.right, 0) - Math.min(w, drawBounds.left);
+ }
if (Math.abs(w) > boundsWidth) {
return w;
} else {
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 51d7caa..65d9b3a 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -291,6 +291,15 @@
int getDefaultDisplayRotation();
/**
+ * Retrieve the display user rotation.
+ * @param displayId Id of the display
+ * @return Rotation one of {@link android.view.Surface#ROTATION_0},
+ * {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180},
+ * {@link android.view.Surface#ROTATION_270} or -1 if display is not found.
+ */
+ int getDisplayUserRotation(int displayId);
+
+ /**
* Watch the rotation of the specified screen. Returns the current rotation,
* calls back when it changes.
*/
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a355f55..2a1eb97 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3809,6 +3809,7 @@
* 1 PFLAG4_IS_COUNTED_AS_SENSITIVE
* 1 PFLAG4_HAS_DRAWN
* 1 PFLAG4_HAS_MOVED
+ * 1 PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION
* |-------|-------|-------|-------|
*/
@@ -3954,6 +3955,11 @@
*/
private static final int PFLAG4_HAS_MOVED = 0x10000000;
+ /**
+ * Whether the invalidateViewProperty is involked at current frame.
+ */
+ private static final int PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION = 0x20000000;
+
/* End of masks for mPrivateFlags4 */
/** @hide */
@@ -20945,6 +20951,7 @@
} else {
damageInParent();
}
+ mPrivateFlags4 |= PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION;
}
/**
@@ -23641,14 +23648,6 @@
return renderNode;
}
- // For VRR to vote the preferred frame rate
- if (sToolkitSetFrameRateReadOnlyFlagValue
- && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
- votePreferredFrameRate();
- }
-
- mPrivateFlags4 = (mPrivateFlags4 & ~PFLAG4_HAS_MOVED) | PFLAG4_HAS_DRAWN;
-
if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
|| !renderNode.hasDisplayList()
|| (mRecreateDisplayList)) {
@@ -23691,6 +23690,14 @@
mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
+ // // For VRR to vote the preferred frame rate
+ if (sToolkitSetFrameRateReadOnlyFlagValue
+ && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
+ votePreferredFrameRate();
+ }
+
+ mPrivateFlags4 |= PFLAG4_HAS_DRAWN;
+
// Fast path for layouts with no backgrounds
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
dispatchDraw(canvas);
@@ -23710,10 +23717,19 @@
setDisplayListProperties(renderNode);
}
} else {
+ if ((mPrivateFlags4 & PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION)
+ == PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION) {
+ // For VRR to vote the preferred frame rate
+ if (sToolkitSetFrameRateReadOnlyFlagValue
+ && sToolkitFrameRateViewEnablingReadOnlyFlagValue) {
+ votePreferredFrameRate();
+ }
+ mPrivateFlags4 &= ~PFLAG4_HAS_VIEW_PROPERTY_INVALIDATION;
+ }
mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
}
-
+ mPrivateFlags4 &= ~PFLAG4_HAS_MOVED;
mFrameContentVelocity = -1;
return renderNode;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3f078c8..84cde0d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -12714,7 +12714,7 @@
if (frameRateCategory > mPreferredFrameRateCategory) {
mPreferredFrameRateCategory = frameRateCategory;
mFrameRateCategoryChangeReason = reason;
-// mFrameRateCategoryView = view == null ? "-" : view.getClass().getSimpleName();
+ // mFrameRateCategoryView = view == null ? "-" : view.getClass().getSimpleName();
}
mHasInvalidation = true;
mDrawnThisFrame = true;
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 6c852c3..86e5bea 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -76,6 +76,21 @@
"android.view.ViewStructure.extra.FIRST_ACTIVE_POSITION";
/**
+ * Key used for writing the type of the view that generated the virtual structure of its
+ * children.
+ *
+ * For example, if the virtual structure is generated by a webview, the value would be
+ * "WebView". If the virtual structure is generated by a compose view, then the value would be
+ * "ComposeView". The value is of type String.
+ *
+ * This value is added to mainly help with debugging purpose.
+ *
+ * @hide
+ */
+ public static final String EXTRA_VIRTUAL_STRUCTURE_TYPE =
+ "android.view.ViewStructure.extra.VIRTUAL_STRUCTURE_TYPE";
+
+ /**
* Set the identifier for this view.
*
* @param id The view's identifier, as per {@link View#getId View.getId()}.
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index fbb5116..fb1c331 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -11254,8 +11254,10 @@
width = des;
} else {
if (mUseBoundsForWidth) {
- width = Math.max(boring.width,
- (int) Math.ceil(boring.getDrawingBoundingBox().width()));
+ RectF bbox = boring.getDrawingBoundingBox();
+ float rightMax = Math.max(bbox.right, boring.width);
+ float leftMin = Math.min(bbox.left, 0);
+ width = Math.max(boring.width, (int) Math.ceil(rightMax - leftMin));
} else {
width = boring.width;
}
diff --git a/core/java/android/window/WindowTokenClient.java b/core/java/android/window/WindowTokenClient.java
index 1ffb4ff..cc54a93 100644
--- a/core/java/android/window/WindowTokenClient.java
+++ b/core/java/android/window/WindowTokenClient.java
@@ -19,6 +19,8 @@
import static android.window.ConfigurationHelper.isDifferentDisplay;
import static android.window.ConfigurationHelper.shouldUpdateResources;
+import static com.android.window.flags.Flags.windowTokenConfigThreadSafe;
+
import android.annotation.AnyThread;
import android.annotation.MainThread;
import android.annotation.NonNull;
@@ -144,9 +146,8 @@
if (context == null) {
return;
}
- if (shouldReportConfigChange) {
- // Only report to ClientTransactionListenerController when shouldReportConfigChange,
- // which is on the MainThread.
+ if (shouldReportConfigChange && windowTokenConfigThreadSafe()) {
+ // Only report to ClientTransactionListenerController when shouldReportConfigChange.
final ClientTransactionListenerController controller =
getClientTransactionListenerController();
controller.onContextConfigurationPreChanged(context);
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index b9c15c5..55927cc 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -57,3 +57,10 @@
description: "Enables desktop wallpaper activity to show wallpaper in the desktop mode"
bug: "309014605"
}
+
+flag {
+ name: "enable_desktop_windowing_immersive_handle_hiding"
+ namespace: "lse_desktop_experience"
+ description: "Hides the App Handle when in fullscreen immersive mode"
+ bug: "336368019"
+}
diff --git a/core/java/android/window/flags/windowing_sdk.aconfig b/core/java/android/window/flags/windowing_sdk.aconfig
index 6c00c70..001ed79 100644
--- a/core/java/android/window/flags/windowing_sdk.aconfig
+++ b/core/java/android/window/flags/windowing_sdk.aconfig
@@ -93,6 +93,16 @@
flag {
namespace: "windowing_sdk"
+ name: "window_token_config_thread_safe"
+ description: "Ensure the Configuration pre/post changed is thread safe"
+ bug: "334285008"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ namespace: "windowing_sdk"
name: "always_defer_transition_when_apply_wct"
description: "Report error when defer transition fails when it should not"
bug: "335562144"
diff --git a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
index 83e9407..e2005d7 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
@@ -259,7 +259,9 @@
final int extensionFlags = src.readInt();
if ((extensionFlags & BatteryStatsHistory.EXTENSION_POWER_STATS_DESCRIPTOR_FLAG) != 0) {
PowerStats.Descriptor descriptor = PowerStats.Descriptor.readSummaryFromParcel(src);
- mDescriptorRegistry.register(descriptor);
+ if (descriptor != null) {
+ mDescriptorRegistry.register(descriptor);
+ }
}
if ((extensionFlags & BatteryStatsHistory.EXTENSION_POWER_STATS_FLAG) != 0) {
cur.powerStats = PowerStats.readFromParcel(src, mDescriptorRegistry);
diff --git a/core/java/com/android/internal/os/flags.aconfig b/core/java/com/android/internal/os/flags.aconfig
index 4c2bbd4..c8d6810 100644
--- a/core/java/com/android/internal/os/flags.aconfig
+++ b/core/java/com/android/internal/os/flags.aconfig
@@ -1,4 +1,5 @@
package: "com.android.internal.os"
+container: "system"
flag {
name: "enable_apache_http_legacy_preload"
@@ -7,4 +8,4 @@
# Fixed read-only is required as the flag is read during zygote init.
is_fixed_read_only: true
bug: "241474956"
-}
\ No newline at end of file
+}
diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
index b6558cb..b3e1df1 100644
--- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
@@ -16,34 +16,34 @@
package com.android.internal.protolog;
-import static android.internal.perfetto.protos.PerfettoTrace.InternedData.PROTOLOG_STACKTRACE;
-import static android.internal.perfetto.protos.PerfettoTrace.InternedData.PROTOLOG_STRING_ARGS;
-import static android.internal.perfetto.protos.PerfettoTrace.InternedString.IID;
-import static android.internal.perfetto.protos.PerfettoTrace.InternedString.STR;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogMessage.BOOLEAN_PARAMS;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogMessage.DOUBLE_PARAMS;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogMessage.MESSAGE_ID;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogMessage.SINT64_PARAMS;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogMessage.STACKTRACE_IID;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogMessage.STR_PARAM_IIDS;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.GROUPS;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.Group.ID;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.Group.NAME;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.Group.TAG;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MESSAGES;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData.GROUP_ID;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData.LEVEL;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData.MESSAGE;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.INTERNED_DATA;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.PROTOLOG_MESSAGE;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.PROTOLOG_VIEWER_CONFIG;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.SEQUENCE_FLAGS;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.SEQ_INCREMENTAL_STATE_CLEARED;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.SEQ_NEEDS_INCREMENTAL_STATE;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.TIMESTAMP;
+import static android.internal.perfetto.protos.InternedDataOuterClass.InternedData.PROTOLOG_STACKTRACE;
+import static android.internal.perfetto.protos.InternedDataOuterClass.InternedData.PROTOLOG_STRING_ARGS;
+import static android.internal.perfetto.protos.ProfileCommon.InternedString.IID;
+import static android.internal.perfetto.protos.ProfileCommon.InternedString.STR;
+import static android.internal.perfetto.protos.Protolog.ProtoLogMessage.BOOLEAN_PARAMS;
+import static android.internal.perfetto.protos.Protolog.ProtoLogMessage.DOUBLE_PARAMS;
+import static android.internal.perfetto.protos.Protolog.ProtoLogMessage.MESSAGE_ID;
+import static android.internal.perfetto.protos.Protolog.ProtoLogMessage.SINT64_PARAMS;
+import static android.internal.perfetto.protos.Protolog.ProtoLogMessage.STACKTRACE_IID;
+import static android.internal.perfetto.protos.Protolog.ProtoLogMessage.STR_PARAM_IIDS;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.GROUPS;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.Group.ID;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.Group.NAME;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.Group.TAG;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MESSAGES;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.GROUP_ID;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.LEVEL;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.INTERNED_DATA;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.PROTOLOG_MESSAGE;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.PROTOLOG_VIEWER_CONFIG;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.SEQUENCE_FLAGS;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.SEQ_INCREMENTAL_STATE_CLEARED;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.SEQ_NEEDS_INCREMENTAL_STATE;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.TIMESTAMP;
import android.annotation.Nullable;
-import android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData;
+import android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.Trace;
diff --git a/core/java/com/android/internal/protolog/ProtoLogDataSource.java b/core/java/com/android/internal/protolog/ProtoLogDataSource.java
index e79bf36..6ab79b9 100644
--- a/core/java/com/android/internal/protolog/ProtoLogDataSource.java
+++ b/core/java/com/android/internal/protolog/ProtoLogDataSource.java
@@ -16,14 +16,16 @@
package com.android.internal.protolog;
-import static android.internal.perfetto.protos.PerfettoTrace.DataSourceConfig.PROTOLOG_CONFIG;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogConfig.GROUP_OVERRIDES;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogConfig.TRACING_MODE;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogGroup.COLLECT_STACKTRACE;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogGroup.GROUP_NAME;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogGroup.LOG_FROM;
+import static android.internal.perfetto.protos.ProtologConfig.ProtoLogConfig.DEFAULT;
+import static android.internal.perfetto.protos.ProtologConfig.ProtoLogConfig.ENABLE_ALL;
+import static android.internal.perfetto.protos.ProtologConfig.ProtoLogConfig.GROUP_OVERRIDES;
+import static android.internal.perfetto.protos.ProtologConfig.ProtoLogConfig.TRACING_MODE;
+import static android.internal.perfetto.protos.ProtologConfig.ProtoLogGroup.COLLECT_STACKTRACE;
+import static android.internal.perfetto.protos.ProtologConfig.ProtoLogGroup.GROUP_NAME;
+import static android.internal.perfetto.protos.ProtologConfig.ProtoLogGroup.LOG_FROM;
-import android.internal.perfetto.protos.PerfettoTrace;
+import android.internal.perfetto.protos.DataSourceConfigOuterClass.DataSourceConfig;
+import android.internal.perfetto.protos.ProtologCommon;
import android.tracing.perfetto.CreateIncrementalStateArgs;
import android.tracing.perfetto.CreateTlsStateArgs;
import android.tracing.perfetto.DataSource;
@@ -65,7 +67,7 @@
try {
while (configStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
try {
- if (configStream.getFieldNumber() == (int) PROTOLOG_CONFIG) {
+ if (configStream.getFieldNumber() == (int) DataSourceConfig.PROTOLOG_CONFIG) {
if (config != null) {
throw new RuntimeException("ProtoLog config already set in loop");
}
@@ -179,7 +181,7 @@
private ProtoLogConfig readProtoLogConfig(ProtoInputStream configStream)
throws IOException {
- final long config_token = configStream.start(PROTOLOG_CONFIG);
+ final long config_token = configStream.start(DataSourceConfig.PROTOLOG_CONFIG);
LogLevel defaultLogFromLevel = LogLevel.WTF;
final Map<String, GroupConfig> groupConfigs = new HashMap<>();
@@ -188,9 +190,9 @@
if (configStream.getFieldNumber() == (int) TRACING_MODE) {
int tracingMode = configStream.readInt(TRACING_MODE);
switch (tracingMode) {
- case PerfettoTrace.ProtoLogConfig.DEFAULT:
+ case DEFAULT:
break;
- case PerfettoTrace.ProtoLogConfig.ENABLE_ALL:
+ case ENABLE_ALL:
defaultLogFromLevel = LogLevel.DEBUG;
break;
default:
@@ -210,27 +212,27 @@
if (configStream.getFieldNumber() == (int) LOG_FROM) {
final int logFromInt = configStream.readInt(LOG_FROM);
switch (logFromInt) {
- case (PerfettoTrace.PROTOLOG_LEVEL_DEBUG): {
+ case (ProtologCommon.PROTOLOG_LEVEL_DEBUG): {
logFromLevel = LogLevel.DEBUG;
break;
}
- case (PerfettoTrace.PROTOLOG_LEVEL_VERBOSE): {
+ case (ProtologCommon.PROTOLOG_LEVEL_VERBOSE): {
logFromLevel = LogLevel.VERBOSE;
break;
}
- case (PerfettoTrace.PROTOLOG_LEVEL_INFO): {
+ case (ProtologCommon.PROTOLOG_LEVEL_INFO): {
logFromLevel = LogLevel.INFO;
break;
}
- case (PerfettoTrace.PROTOLOG_LEVEL_WARN): {
+ case (ProtologCommon.PROTOLOG_LEVEL_WARN): {
logFromLevel = LogLevel.WARN;
break;
}
- case (PerfettoTrace.PROTOLOG_LEVEL_ERROR): {
+ case (ProtologCommon.PROTOLOG_LEVEL_ERROR): {
logFromLevel = LogLevel.ERROR;
break;
}
- case (PerfettoTrace.PROTOLOG_LEVEL_WTF): {
+ case (ProtologCommon.PROTOLOG_LEVEL_WTF): {
logFromLevel = LogLevel.WTF;
break;
}
diff --git a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
index 88a7b54..b7b2424 100644
--- a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
+++ b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
@@ -1,8 +1,8 @@
package com.android.internal.protolog;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MESSAGES;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData.MESSAGE;
-import static android.internal.perfetto.protos.PerfettoTrace.ProtoLogViewerConfig.MessageData.MESSAGE_ID;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MESSAGES;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE;
+import static android.internal.perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.MESSAGE_ID;
import android.util.ArrayMap;
import android.util.proto.ProtoInputStream;
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 969f95d..792c223 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -81,4 +81,5 @@
void onCallBackModeStarted(int type);
void onCallBackModeStopped(int type, int reason);
void onSimultaneousCallingStateChanged(in int[] subIds);
+ void onCarrierRoamingNtnModeChanged(in boolean active);
}
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 0203ea4..04332cd 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -120,4 +120,5 @@
void notifyCallbackModeStarted(int phoneId, int subId, int type);
void notifyCallbackModeStopped(int phoneId, int subId, int type, int reason);
+ void notifyCarrierRoamingNtnModeChanged(int subId, in boolean active);
}
diff --git a/core/java/com/android/internal/widget/BigPictureNotificationImageView.java b/core/java/com/android/internal/widget/BigPictureNotificationImageView.java
index f95f5db..7e7aba2 100644
--- a/core/java/com/android/internal/widget/BigPictureNotificationImageView.java
+++ b/core/java/com/android/internal/widget/BigPictureNotificationImageView.java
@@ -26,6 +26,7 @@
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.util.AttributeSet;
+import android.util.Log;
import android.widget.ImageView;
import android.widget.RemoteViews;
@@ -126,11 +127,19 @@
private Drawable loadImage(Icon icon) {
if (icon == null) return null;
+
Drawable drawable = LocalImageResolver.resolveImage(icon, mContext, mMaximumDrawableWidth,
mMaximumDrawableHeight);
- if (drawable == null) {
- return icon.loadDrawable(mContext);
+ if (drawable != null) {
+ return drawable;
}
- return drawable;
+
+ drawable = icon.loadDrawable(mContext);
+ if (drawable != null) {
+ return drawable;
+ }
+
+ Log.e(TAG, "Couldn't load drawable for icon: " + icon);
+ return null;
}
}
diff --git a/core/java/com/android/internal/widget/LocalImageResolver.java b/core/java/com/android/internal/widget/LocalImageResolver.java
index 9ef7ce38..c5d74fc 100644
--- a/core/java/com/android/internal/widget/LocalImageResolver.java
+++ b/core/java/com/android/internal/widget/LocalImageResolver.java
@@ -132,7 +132,11 @@
// Fallback to straight drawable load if we fail with more efficient approach.
try {
- return icon.loadDrawable(context);
+ final Drawable iconDrawable = icon.loadDrawable(context);
+ if (iconDrawable == null) {
+ Log.w(TAG, "Couldn't load drawable for icon: " + icon);
+ }
+ return iconDrawable;
} catch (Resources.NotFoundException e) {
return null;
}
@@ -233,8 +237,7 @@
});
// ImageDecoder documentation is misleading a bit - it'll throw NotFoundException
- // in some cases despite it not saying so. Rethrow it as an IOException to keep
- // our API contract.
+ // in some cases despite it not saying so.
} catch (IOException | Resources.NotFoundException e) {
Log.d(TAG, "Couldn't use ImageDecoder for drawable, falling back to non-resized load.");
return null;
diff --git a/core/jni/com_android_internal_content_FileSystemUtils.cpp b/core/jni/com_android_internal_content_FileSystemUtils.cpp
index 01920de..31f4e64 100644
--- a/core/jni/com_android_internal_content_FileSystemUtils.cpp
+++ b/core/jni/com_android_internal_content_FileSystemUtils.cpp
@@ -21,6 +21,7 @@
#include <android-base/file.h>
#include <android-base/hex.h>
#include <android-base/unique_fd.h>
+#include <bionic/macros.h>
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
@@ -35,10 +36,45 @@
#include <fstream>
#include <vector>
+using android::base::borrowed_fd;
using android::base::HexString;
using android::base::ReadFullyAtOffset;
namespace android {
+
+bool punchWithBlockAlignment(borrowed_fd fd, uint64_t start, uint64_t length, uint64_t blockSize) {
+ uint64_t end;
+ if (__builtin_add_overflow(start, length, &end)) {
+ ALOGE("Overflow occurred when calculating end");
+ return false;
+ }
+
+ start = align_up(start, blockSize);
+ end = align_down(end, blockSize);
+
+ uint64_t alignedLength;
+ if (__builtin_sub_overflow(end, start, &alignedLength)) {
+ ALOGE("Overflow occurred when calculating length");
+ return false;
+ }
+
+ if (alignedLength < blockSize) {
+ ALOGW("Skipping punching hole as aligned length is less than block size");
+ return false;
+ }
+
+ ALOGD("Punching hole in file - start: %" PRIu64 " len:%" PRIu64 "", start, alignedLength);
+
+ int result =
+ fallocate(fd.get(), FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, start, alignedLength);
+ if (result < 0) {
+ ALOGE("fallocate failed to punch hole, error:%d", errno);
+ return false;
+ }
+
+ return true;
+}
+
bool punchHoles(const char *filePath, const uint64_t offset,
const std::vector<Elf64_Phdr> &programHeaders) {
struct stat64 beforePunch;
@@ -96,6 +132,8 @@
continue;
}
+ // if we have a uncompressed file which is being opened from APK, use the offset to
+ // punch native lib inside Apk.
uint64_t punchStartOffset;
if (__builtin_add_overflow(offset, punchOffset, &punchStartOffset)) {
ALOGE("Overflow occurred when calculating length");
@@ -144,12 +182,7 @@
position = uncheckedChunkEnd;
}
- // if we have a uncompressed file which is being opened from APK, use the offset to
- // punch native lib inside Apk.
- int result = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, punchStartOffset,
- punchLen);
- if (result < 0) {
- ALOGE("fallocate failed to punch hole, error:%d", errno);
+ if (!punchWithBlockAlignment(fd, punchStartOffset, punchLen, blockSize)) {
return false;
}
}
@@ -298,13 +331,7 @@
return false;
}
- ALOGD("Punching hole in apk start: %" PRIu64 " len:%" PRIu64 "", punchOffset, punchLen);
-
- // Punch hole for this entire stretch.
- int result = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, punchOffset,
- punchLen);
- if (result < 0) {
- ALOGE("fallocate failed to punch hole inside apk, error:%d", errno);
+ if (!punchWithBlockAlignment(fd, punchOffset, punchLen, blockSize)) {
return false;
}
}
diff --git a/core/res/res/drawable/ic_android_satellite_24px.xml b/core/res/res/drawable/ic_android_satellite_24px.xml
new file mode 100644
index 0000000..15f2884
--- /dev/null
+++ b/core/res/res/drawable/ic_android_satellite_24px.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="960"
+ android:viewportHeight="960"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M487,600L392,505L346,551L376,580Q399,603 399,637Q399,671 376,694L333,737Q310,760 276.5,760Q243,760 220,737L103,620Q80,597 80,563.5Q80,530 103,507L146,464Q169,441 203,441Q237,441 260,464L289,494L335,448L160,273L273,160L448,335L493,290L464,260Q441,237 441,203Q441,169 464,146L507,103Q530,80 563.5,80Q597,80 620,103L737,220Q760,243 760,276.5Q760,310 737,333L694,376Q671,399 637,399Q603,399 580,376L550,347L505,392L600,487L487,600ZM520,880L520,800Q637,800 718.5,718.5Q800,637 800,520L880,520Q880,595 851.5,660.5Q823,726 774.5,774.5Q726,823 660.5,851.5Q595,880 520,880ZM520,720L520,640Q570,640 605,605Q640,570 640,520L720,520Q720,603 661.5,661.5Q603,720 520,720ZM520,203L550,233L593,190L563,160Q563,160 563,160Q563,160 563,160L520,203Q520,203 520,203Q520,203 520,203ZM160,563L190,593L233,550L203,520Q203,520 203,520Q203,520 203,520L160,563Q160,563 160,563Q160,563 160,563ZM637,320L680,277Q680,277 680,277Q680,277 680,277L650,247L607,290L637,320Q637,320 637,320Q637,320 637,320ZM277,680L320,637Q320,637 320,637Q320,637 320,637L290,607L247,650L277,680Q277,680 277,680Q277,680 277,680Z"/>
+</vector>
diff --git a/core/res/res/values/config_battery_stats.xml b/core/res/res/values/config_battery_stats.xml
index ae47899..8d97362 100644
--- a/core/res/res/values/config_battery_stats.xml
+++ b/core/res/res/values/config_battery_stats.xml
@@ -35,6 +35,9 @@
<!-- Mobile Radio power stats collection throttle period in milliseconds. -->
<integer name="config_defaultPowerStatsThrottlePeriodMobileRadio">3600000</integer>
+ <!-- Mobile Radio power stats collection throttle period in milliseconds. -->
+ <integer name="config_defaultPowerStatsThrottlePeriodWifi">3600000</integer>
+
<!-- PowerStats aggregation period in milliseconds. This is the interval at which the power
stats aggregation procedure is performed and the results stored in PowerStatsStore. -->
<integer name="config_powerStatsAggregationPeriod">14400000</integer>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 60289c1..e96240d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1018,6 +1018,9 @@
<!-- The title to use when a dream is opened in preview mode. [CHAR LIMIT=NONE] -->
<string name="dream_preview_title">Preview, <xliff:g id="dream_name" example="Clock">%1$s</xliff:g></string>
+ <!-- The title to use when a dream is open in accessibility mode to let users know to double tap to dismiss the dream [CHAR LIMIT=32] -->
+ <string name="dream_accessibility_action_click">dismiss</string>
+
<!-- Permissions -->
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ead5827..0bf6347 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4471,6 +4471,7 @@
<java-symbol type="string" name="capability_title_canTakeScreenshot" />
<java-symbol type="string" name="dream_preview_title" />
+ <java-symbol type="string" name="dream_accessibility_action_click" />
<java-symbol type="string" name="config_servicesExtensionPackage" />
@@ -5218,6 +5219,7 @@
<java-symbol type="bool" name="config_batteryStatsResetOnUnplugAfterSignificantCharge" />
<java-symbol type="integer" name="config_defaultPowerStatsThrottlePeriodCpu" />
<java-symbol type="integer" name="config_defaultPowerStatsThrottlePeriodMobileRadio" />
+ <java-symbol type="integer" name="config_defaultPowerStatsThrottlePeriodWifi" />
<java-symbol type="integer" name="config_powerStatsAggregationPeriod" />
<java-symbol type="integer" name="config_aggregatedPowerStatsSpanDuration" />
@@ -5380,6 +5382,7 @@
<java-symbol type="string" name="satellite_notification_open_message" />
<java-symbol type="string" name="satellite_notification_how_it_works" />
<java-symbol type="drawable" name="ic_satellite_alt_24px" />
+ <java-symbol type="drawable" name="ic_android_satellite_24px" />
<!-- DisplayManager configs. -->
<java-symbol type="bool" name="config_evenDimmerEnabled" />
diff --git a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
index f8c2d6a..b6f4429 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ClientTransactionListenerControllerTest.java
@@ -21,6 +21,7 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.window.flags.Flags.FLAG_BUNDLE_CLIENT_TRANSACTION_FLAG;
+import static com.android.window.flags.Flags.FLAG_WINDOW_TOKEN_CONFIG_THREAD_SAFE;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -189,6 +190,8 @@
@Test
public void testWindowTokenClient_onConfigurationChanged() {
+ mSetFlagsRule.enableFlags(FLAG_WINDOW_TOKEN_CONFIG_THREAD_SAFE);
+
doNothing().when(mController).onContextConfigurationPreChanged(any());
doNothing().when(mController).onContextConfigurationPostChanged(any());
diff --git a/core/tests/coretests/src/android/database/DatabaseUtilsTest.java b/core/tests/coretests/src/android/database/DatabaseUtilsTest.java
index 2323527..e25fdf9 100644
--- a/core/tests/coretests/src/android/database/DatabaseUtilsTest.java
+++ b/core/tests/coretests/src/android/database/DatabaseUtilsTest.java
@@ -78,7 +78,8 @@
final int sel = STATEMENT_SELECT;
assertEquals(sel, getSqlStatementType("SELECT"));
assertEquals(sel, getSqlStatementType(" SELECT"));
- assertEquals(sel, getSqlStatementType(" \n SELECT"));
+ assertEquals(sel, getSqlStatementType(" \n\r\f\t SELECT"));
+ assertEquals(sel, getSqlStatementType(" \n\r\f\t SEL"));
final int upd = STATEMENT_UPDATE;
assertEquals(upd, getSqlStatementType("UPDATE"));
@@ -89,12 +90,21 @@
assertEquals(ddl, getSqlStatementType("ALTER TABLE t1 ADD COLUMN j int"));
assertEquals(ddl, getSqlStatementType("CREATE TABLE t1 (i int)"));
+ // Verify that the answers are case-insensitive
+ assertEquals(sel, getSqlStatementType("select"));
+ assertEquals(sel, getSqlStatementType("sElect"));
+ assertEquals(sel, getSqlStatementType("sELECT"));
+ assertEquals(sel, getSqlStatementType("seLECT"));
+
// Short statements, leading comments, and WITH are decoded to "other" in the public API.
final int othr = STATEMENT_OTHER;
assertEquals(othr, getSqlStatementType("SE"));
assertEquals(othr, getSqlStatementType("SE LECT"));
assertEquals(othr, getSqlStatementType("-- cmt\n SE"));
assertEquals(othr, getSqlStatementType("WITH"));
+ assertEquals(othr, getSqlStatementType("-"));
+ assertEquals(othr, getSqlStatementType("--"));
+ assertEquals(othr, getSqlStatementType("*/* foo */ SEL"));
// Verify that leading line-comments are skipped.
assertEquals(sel, getSqlStatementType("-- cmt\n SELECT"));
diff --git a/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java b/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java
index 030d420..6ae3d65 100644
--- a/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java
+++ b/core/tests/coretests/src/android/tracing/perfetto/DataSourceTest.java
@@ -16,14 +16,15 @@
package android.tracing.perfetto;
-import static android.internal.perfetto.protos.PerfettoTrace.TestEvent.PAYLOAD;
-import static android.internal.perfetto.protos.PerfettoTrace.TestEvent.TestPayload.SINGLE_INT;
-import static android.internal.perfetto.protos.PerfettoTrace.TracePacket.FOR_TESTING;
+import static android.internal.perfetto.protos.TestEventOuterClass.TestEvent.PAYLOAD;
+import static android.internal.perfetto.protos.TestEventOuterClass.TestEvent.TestPayload.SINGLE_INT;
+import static android.internal.perfetto.protos.TracePacketOuterClass.TracePacket.FOR_TESTING;
import static java.io.File.createTempFile;
import static java.nio.file.Files.createTempDirectory;
-import android.internal.perfetto.protos.PerfettoTrace;
+import android.internal.perfetto.protos.DataSourceConfigOuterClass.DataSourceConfig;
+import android.internal.perfetto.protos.TestConfigOuterClass.TestConfig;
import android.tools.ScenarioBuilder;
import android.tools.Tag;
import android.tools.io.TraceType;
@@ -46,6 +47,9 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import perfetto.protos.PerfettoConfig;
+import perfetto.protos.TracePacketOuterClass;
+
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
@@ -56,9 +60,6 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
-import perfetto.protos.PerfettoConfig;
-import perfetto.protos.TracePacketOuterClass;
-
@RunWith(AndroidJUnit4.class)
public class DataSourceTest {
private final File mTracingDirectory = createTempDirectory("temp").toFile();
@@ -328,19 +329,19 @@
int configDummyIntValue = 0;
while (configStream.get().nextField() != ProtoInputStream.NO_MORE_FIELDS) {
if (configStream.get().getFieldNumber()
- == (int) PerfettoTrace.DataSourceConfig.FOR_TESTING) {
+ == (int) DataSourceConfig.FOR_TESTING) {
final long forTestingToken = configStream.get()
- .start(PerfettoTrace.DataSourceConfig.FOR_TESTING);
+ .start(DataSourceConfig.FOR_TESTING);
while (configStream.get().nextField() != ProtoInputStream.NO_MORE_FIELDS) {
if (configStream.get().getFieldNumber()
- == (int) PerfettoTrace.TestConfig.DUMMY_FIELDS) {
+ == (int) TestConfig.DUMMY_FIELDS) {
final long dummyFieldsToken = configStream.get()
- .start(PerfettoTrace.TestConfig.DUMMY_FIELDS);
+ .start(TestConfig.DUMMY_FIELDS);
while (configStream.get().nextField() != ProtoInputStream.NO_MORE_FIELDS) {
if (configStream.get().getFieldNumber()
- == (int) PerfettoTrace.TestConfig.DummyFields.FIELD_INT32) {
+ == (int) TestConfig.DummyFields.FIELD_INT32) {
int val = configStream.get().readInt(
- PerfettoTrace.TestConfig.DummyFields.FIELD_INT32);
+ TestConfig.DummyFields.FIELD_INT32);
if (val != 0) {
configDummyIntValue = val;
break;
diff --git a/core/tests/coretests/src/android/view/ViewFrameRateTest.java b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
index 0bf9a4c..4b9aaae 100644
--- a/core/tests/coretests/src/android/view/ViewFrameRateTest.java
+++ b/core/tests/coretests/src/android/view/ViewFrameRateTest.java
@@ -419,6 +419,7 @@
FLAG_TOOLKIT_FRAME_RATE_VELOCITY_MAPPING_READ_ONLY
})
public void frameRateAndCategory() throws Throwable {
+ mMovingView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
waitForFrameRateCategoryToSettle();
mActivityRule.runOnUiThread(() -> {
mMovingView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_LOW);
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index ccebd03..20fb6e3 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -754,39 +754,39 @@
@RequiresFlagsEnabled({FLAG_TOOLKIT_SET_FRAME_RATE_READ_ONLY,
FLAG_TOOLKIT_FRAME_RATE_VIEW_ENABLING_READ_ONLY})
public void votePreferredFrameRate_voteFrameRateCategory_aggregate() {
- View mView1 = new View(sContext);
- attachViewToWindow(mView1);
- ViewRootImpl viewRootImpl = mView1.getViewRootImpl();
+ mView = new View(sContext);
+ attachViewToWindow(mView);
+ mViewRootImpl = mView.getViewRootImpl();
sInstrumentation.runOnMainSync(() -> {
assertEquals(FRAME_RATE_CATEGORY_DEFAULT,
- viewRootImpl.getPreferredFrameRateCategory());
+ mViewRootImpl.getPreferredFrameRateCategory());
});
// reset the frame rate category counts
for (int i = 0; i < 5; i++) {
sInstrumentation.runOnMainSync(() -> {
- mView1.setRequestedFrameRate(mView1.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
- mView1.invalidate();
+ mView.setRequestedFrameRate(View.REQUESTED_FRAME_RATE_CATEGORY_NO_PREFERENCE);
+ mView.invalidate();
});
sInstrumentation.waitForIdleSync();
}
sInstrumentation.runOnMainSync(() -> {
- viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_LOW, 0, null);
- assertEquals(FRAME_RATE_CATEGORY_LOW, viewRootImpl.getPreferredFrameRateCategory());
- viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_NORMAL, 0, null);
- assertEquals(FRAME_RATE_CATEGORY_NORMAL, viewRootImpl.getPreferredFrameRateCategory());
- viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_HIGH_HINT, 0, null);
+ mViewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_LOW, 0, null);
+ assertEquals(FRAME_RATE_CATEGORY_LOW, mViewRootImpl.getPreferredFrameRateCategory());
+ mViewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_NORMAL, 0, null);
+ assertEquals(FRAME_RATE_CATEGORY_NORMAL, mViewRootImpl.getPreferredFrameRateCategory());
+ mViewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_HIGH_HINT, 0, null);
assertEquals(FRAME_RATE_CATEGORY_HIGH_HINT,
- viewRootImpl.getPreferredFrameRateCategory());
- viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_HIGH, 0, null);
- assertEquals(FRAME_RATE_CATEGORY_HIGH, viewRootImpl.getPreferredFrameRateCategory());
- viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_HIGH_HINT, 0, null);
- assertEquals(FRAME_RATE_CATEGORY_HIGH, viewRootImpl.getPreferredFrameRateCategory());
- viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_NORMAL, 0, null);
- assertEquals(FRAME_RATE_CATEGORY_HIGH, viewRootImpl.getPreferredFrameRateCategory());
- viewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_LOW, 0, null);
- assertEquals(FRAME_RATE_CATEGORY_HIGH, viewRootImpl.getPreferredFrameRateCategory());
+ mViewRootImpl.getPreferredFrameRateCategory());
+ mViewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_HIGH, 0, null);
+ assertEquals(FRAME_RATE_CATEGORY_HIGH, mViewRootImpl.getPreferredFrameRateCategory());
+ mViewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_HIGH_HINT, 0, null);
+ assertEquals(FRAME_RATE_CATEGORY_HIGH, mViewRootImpl.getPreferredFrameRateCategory());
+ mViewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_NORMAL, 0, null);
+ assertEquals(FRAME_RATE_CATEGORY_HIGH, mViewRootImpl.getPreferredFrameRateCategory());
+ mViewRootImpl.votePreferredFrameRateCategory(FRAME_RATE_CATEGORY_LOW, 0, null);
+ assertEquals(FRAME_RATE_CATEGORY_HIGH, mViewRootImpl.getPreferredFrameRateCategory());
});
}
@@ -947,8 +947,9 @@
mView.invalidate();
runAfterDraw(() -> {
if (toolkitFrameRateVelocityMappingReadOnly()) {
- assertEquals(FRAME_RATE_CATEGORY_LOW,
- mViewRootImpl.getLastPreferredFrameRateCategory());
+ int expected = toolkitFrameRateBySizeReadOnly()
+ ? FRAME_RATE_CATEGORY_LOW : FRAME_RATE_CATEGORY_NORMAL;
+ assertEquals(expected, mViewRootImpl.getLastPreferredFrameRateCategory());
assertTrue(mViewRootImpl.getLastPreferredFrameRate() >= 60f);
} else {
assertEquals(FRAME_RATE_CATEGORY_HIGH,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
index 0799fe3..808c212 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityBackAnimation.kt
@@ -283,7 +283,11 @@
scrimLayer = scrimBuilder.build()
val colorComponents = floatArrayOf(0f, 0f, 0f)
maxScrimAlpha = if (isDarkTheme) MAX_SCRIM_ALPHA_DARK else MAX_SCRIM_ALPHA_LIGHT
- val scrimCrop = if (isLetterboxed) backAnimRect else closingTarget!!.localBounds
+ val scrimCrop = if (isLetterboxed) {
+ closingTarget!!.windowConfiguration.bounds
+ } else {
+ closingTarget!!.localBounds
+ }
transaction
.setColor(scrimLayer, colorComponents)
.setAlpha(scrimLayer!!, maxScrimAlpha)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java
index a67821b..0297901 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BadgedImageView.java
@@ -288,13 +288,16 @@
/** Sets the position of the dot and badge, animating them out and back in if requested. */
void animateDotBadgePositions(boolean onLeft) {
- mOnLeft = onLeft;
-
- if (onLeft != getDotOnLeft() && shouldDrawDot()) {
- animateDotScale(0f /* showDot */, () -> {
- invalidate();
- animateDotScale(1.0f, null /* after */);
- });
+ if (onLeft != getDotOnLeft()) {
+ if (shouldDrawDot()) {
+ animateDotScale(0f /* showDot */, () -> {
+ mOnLeft = onLeft;
+ invalidate();
+ animateDotScale(1.0f, null /* after */);
+ });
+ } else {
+ mOnLeft = onLeft;
+ }
}
// TODO animate badge
showBadge();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 74f087b..4e8afcc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -68,6 +68,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.Flags;
import com.android.wm.shell.R;
import com.android.wm.shell.common.AlphaOptimizedButton;
import com.android.wm.shell.common.TriangleShape;
@@ -446,6 +447,8 @@
mManageButton.setVisibility(GONE);
} else {
mTaskView = bubbleTaskView.getTaskView();
+ // reset the insets that might left after TaskView is shown in BubbleBarExpandedView
+ mTaskView.setCaptionInsets(null);
bubbleTaskView.setDelegateListener(mTaskViewListener);
// set a fixed width so it is not recalculated as part of a rotation. the width will be
@@ -668,6 +671,11 @@
}
}
+ /** Sets the alpha for the pointer. */
+ public void setPointerAlpha(float alpha) {
+ mPointerView.setAlpha(alpha);
+ }
+
/**
* Get alpha from underlying {@code TaskView} if this view is for a bubble.
* Or get alpha for the overflow view if this view is for overflow.
@@ -698,12 +706,14 @@
}
}
- /**
- * Sets the alpha of the background and the pointer view.
- */
+ /** Sets the alpha of the background. */
public void setBackgroundAlpha(float alpha) {
- mPointerView.setAlpha(alpha);
- setAlpha(alpha);
+ if (Flags.enableNewBubbleAnimations()) {
+ setAlpha(alpha);
+ } else {
+ mPointerView.setAlpha(alpha);
+ setAlpha(alpha);
+ }
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 8da85d2..dcc536b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -2358,9 +2358,9 @@
} else {
index = getBubbleIndex(mExpandedBubble);
}
- PointF p = mPositioner.getExpandedBubbleXY(index, getState());
+ PointF bubbleXY = mPositioner.getExpandedBubbleXY(index, getState());
final float translationY = mPositioner.getExpandedViewY(mExpandedBubble,
- mPositioner.showBubblesVertically() ? p.y : p.x);
+ mPositioner.showBubblesVertically() ? bubbleXY.y : bubbleXY.x);
mExpandedViewContainer.setTranslationX(0f);
mExpandedViewContainer.setTranslationY(translationY);
mExpandedViewContainer.setAlpha(1f);
@@ -2371,40 +2371,42 @@
? mStackAnimationController.getStackPosition().y
: mStackAnimationController.getStackPosition().x;
final float bubbleWillBeAt = showVertically
- ? p.y
- : p.x;
+ ? bubbleXY.y
+ : bubbleXY.x;
final float distanceAnimated = Math.abs(bubbleWillBeAt - relevantStackPosition);
// Wait for the path animation target to reach its end, and add a small amount of extra time
// if the bubble is moving a lot horizontally.
- long startDelay = 0L;
+ final long startDelay;
// Should not happen since we lay out before expanding, but just in case...
if (getWidth() > 0) {
startDelay = (long)
(ExpandedAnimationController.EXPAND_COLLAPSE_TARGET_ANIM_DURATION * 1.2f
+ (distanceAnimated / getWidth()) * 30);
+ } else {
+ startDelay = 0L;
}
// Set the pivot point for the scale, so the expanded view animates out from the bubble.
if (showVertically) {
float pivotX;
if (mStackOnLeftOrWillBe) {
- pivotX = p.x + mBubbleSize + mExpandedViewPadding;
+ pivotX = bubbleXY.x + mBubbleSize + mExpandedViewPadding;
} else {
- pivotX = p.x - mExpandedViewPadding;
+ pivotX = bubbleXY.x - mExpandedViewPadding;
}
mExpandedViewContainerMatrix.setScale(
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
pivotX,
- p.y + mBubbleSize / 2f);
+ bubbleXY.y + mBubbleSize / 2f);
} else {
mExpandedViewContainerMatrix.setScale(
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
1f - EXPANDED_VIEW_ANIMATE_SCALE_AMOUNT,
- p.x + mBubbleSize / 2f,
- p.y + mBubbleSize + mExpandedViewPadding);
+ bubbleXY.x + mBubbleSize / 2f,
+ bubbleXY.y + mBubbleSize + mExpandedViewPadding);
}
mExpandedViewContainer.setAnimationMatrix(mExpandedViewContainerMatrix);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java
index b87c2f6..7ceaaea 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipBoundsState.java
@@ -125,6 +125,7 @@
private @Nullable Runnable mOnMinimalSizeChangeCallback;
private @Nullable TriConsumer<Boolean, Integer, Boolean> mOnShelfVisibilityChangeCallback;
private List<Consumer<Rect>> mOnPipExclusionBoundsChangeCallbacks = new ArrayList<>();
+ private List<Consumer<Float>> mOnAspectRatioChangedCallbacks = new ArrayList<>();
// the size of the current bounds relative to the max size spec
private float mBoundsScale;
@@ -297,7 +298,12 @@
/** Set the PIP aspect ratio. */
public void setAspectRatio(float aspectRatio) {
- mAspectRatio = aspectRatio;
+ if (Float.compare(mAspectRatio, aspectRatio) != 0) {
+ mAspectRatio = aspectRatio;
+ for (Consumer<Float> callback : mOnAspectRatioChangedCallbacks) {
+ callback.accept(mAspectRatio);
+ }
+ }
}
/** Get the PIP aspect ratio. */
@@ -527,6 +533,23 @@
mOnPipExclusionBoundsChangeCallbacks.remove(onPipExclusionBoundsChangeCallback);
}
+ /** Adds callback to listen on aspect ratio change. */
+ public void addOnAspectRatioChangedCallback(
+ @NonNull Consumer<Float> onAspectRatioChangedCallback) {
+ if (!mOnAspectRatioChangedCallbacks.contains(onAspectRatioChangedCallback)) {
+ mOnAspectRatioChangedCallbacks.add(onAspectRatioChangedCallback);
+ onAspectRatioChangedCallback.accept(mAspectRatio);
+ }
+ }
+
+ /** Removes callback to listen on aspect ratio change. */
+ public void removeOnAspectRatioChangedCallback(
+ @NonNull Consumer<Float> onAspectRatioChangedCallback) {
+ if (mOnAspectRatioChangedCallbacks.contains(onAspectRatioChangedCallback)) {
+ mOnAspectRatioChangedCallbacks.remove(onAspectRatioChangedCallback);
+ }
+ }
+
public LauncherState getLauncherState() {
return mLauncherState;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 73228de..6834e6d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -107,6 +107,7 @@
import com.android.wm.shell.taskview.TaskViewFactoryController;
import com.android.wm.shell.taskview.TaskViewTransitions;
import com.android.wm.shell.transition.HomeTransitionObserver;
+import com.android.wm.shell.transition.MixedTransitionHandler;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
import com.android.wm.shell.unfold.UnfoldAnimationController;
@@ -675,6 +676,22 @@
return new TaskViewTransitions(transitions);
}
+ // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
+ @BindsOptionalOf
+ @DynamicOverride
+ abstract MixedTransitionHandler optionalMixedTransitionHandler();
+
+ @WMSingleton
+ @Provides
+ static Optional<MixedTransitionHandler> provideMixedTransitionHandler(
+ @DynamicOverride Optional<MixedTransitionHandler> mixedTransitionHandler
+ ) {
+ if (mixedTransitionHandler.isPresent()) {
+ return mixedTransitionHandler;
+ }
+ return Optional.empty();
+ }
+
//
// Keyguard transitions (optional feature)
//
@@ -934,6 +951,7 @@
Optional<OneHandedController> oneHandedControllerOptional,
Optional<HideDisplayCutoutController> hideDisplayCutoutControllerOptional,
Optional<ActivityEmbeddingController> activityEmbeddingOptional,
+ Optional<MixedTransitionHandler> mixedTransitionHandler,
Transitions transitions,
StartingWindowController startingWindow,
ProtoLogController protoLogController,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 26e7acb..b574b81 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -87,6 +87,7 @@
import com.android.wm.shell.taskview.TaskViewTransitions;
import com.android.wm.shell.transition.DefaultMixedHandler;
import com.android.wm.shell.transition.HomeTransitionObserver;
+import com.android.wm.shell.transition.MixedTransitionHandler;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
import com.android.wm.shell.unfold.UnfoldAnimationController;
@@ -373,8 +374,9 @@
//
@WMSingleton
+ @DynamicOverride
@Provides
- static DefaultMixedHandler provideDefaultMixedHandler(
+ static MixedTransitionHandler provideMixedTransitionHandler(
ShellInit shellInit,
Optional<SplitScreenController> splitScreenOptional,
@Nullable PipTransitionController pipTransitionController,
@@ -655,7 +657,6 @@
@Provides
static Object provideIndependentShellComponentsToCreate(
DragAndDropController dragAndDropController,
- DefaultMixedHandler defaultMixedHandler,
Optional<DesktopTasksTransitionObserver> desktopTasksTransitionObserverOptional) {
return new Object();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 57cf992..e885262 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -597,6 +597,17 @@
return;
}
+ if (mPipTransitionState.isEnteringPip()
+ && !mPipTransitionState.getInSwipePipToHomeTransition()) {
+ // If we are still entering PiP with Shell playing enter animation, jump-cut to
+ // the end of the enter animation and reschedule exitPip to run after enter-PiP
+ // has finished its transition and allowed the client to draw in PiP mode.
+ mPipTransitionController.end(() -> {
+ exitPip(animationDurationMs, requestEnterSplit);
+ });
+ return;
+ }
+
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"exitPip: %s, state=%s", mTaskInfo.topActivity, mPipTransitionState);
final WindowContainerTransaction wct = new WindowContainerTransaction();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 10b7619..fdde3ee 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -43,7 +43,6 @@
import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP_TO_SPLIT;
import static com.android.wm.shell.transition.Transitions.TRANSIT_REMOVE_PIP;
-import android.animation.Animator;
import android.annotation.IntDef;
import android.app.ActivityManager;
import android.app.TaskInfo;
@@ -348,9 +347,16 @@
@Override
public void end() {
- Animator animator = mPipAnimationController.getCurrentAnimator();
- if (animator != null && animator.isRunning()) {
- animator.end();
+ end(null);
+ }
+
+ @Override
+ public void end(@Nullable Runnable onTransitionEnd) {
+ if (mPipAnimationController.isAnimating()) {
+ mPipAnimationController.getCurrentAnimator().end();
+ }
+ if (onTransitionEnd != null) {
+ onTransitionEnd.run();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
index 32442f7..4f71a02 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
@@ -305,6 +305,14 @@
public void end() {
}
+ /**
+ * End the currently-playing PiP animation.
+ *
+ * @param onTransitionEnd callback to run upon finishing the playing transition.
+ */
+ public void end(@Nullable Runnable onTransitionEnd) {
+ }
+
/** Starts the {@link android.window.SystemPerformanceHinter.HighPerfSession}. */
public void startHighPerfSession() {}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index c1adfff..d8ac8e9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -219,6 +219,7 @@
mMotionHelper, pipTaskOrganizer, mPipBoundsAlgorithm.getSnapAlgorithm(),
this::onAccessibilityShowMenu, this::updateMovementBounds,
this::animateToUnStashedState, mainExecutor);
+ mPipBoundsState.addOnAspectRatioChangedCallback(this::updateMinMaxSize);
// TODO(b/181599115): This should really be initializes as part of the pip controller, but
// until all PIP implementations derive from the controller, just initialize the touch handler
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
index cc8e3e0..472003c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
@@ -208,6 +208,7 @@
new PipResizeGestureHandler(context, pipBoundsAlgorithm, pipBoundsState,
mTouchState, this::updateMovementBounds, pipUiEventLogger,
menuController, mainExecutor, mPipPerfHintController);
+ mPipBoundsState.addOnAspectRatioChangedCallback(this::updateMinMaxSize);
if (PipUtils.isPip2ExperimentEnabled()) {
shellInit.addInitCallback(this::onInit, this);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java
index 35a1fa0..a85188a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskView.java
@@ -30,7 +30,6 @@
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Handler;
-import android.os.Looper;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
@@ -121,6 +120,11 @@
@Override
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
+ if (mTaskViewTaskController.isUsingShellTransitions()) {
+ // No need for additional work as it is already taken care of during
+ // prepareOpenAnimation().
+ return;
+ }
onLocationChanged();
if (taskInfo.taskDescription != null) {
final int bgColor = taskInfo.taskDescription.getBackgroundColor();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
index 196e04e..11aa402 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
@@ -17,6 +17,7 @@
package com.android.wm.shell.taskview;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.view.WindowManager.TRANSIT_CHANGE;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -48,6 +49,23 @@
* TaskView} to {@link TaskViewTaskController} interactions are done via direct method calls.
*
* The reverse communication is done via the {@link TaskViewBase} interface.
+ *
+ * <ul>
+ * <li>The entry point for an activity based task view is {@link
+ * TaskViewTaskController#startActivity(PendingIntent, Intent, ActivityOptions, Rect)}</li>
+ *
+ * <li>The entry point for an activity (represented by {@link ShortcutInfo}) based task view
+ * is {@link TaskViewTaskController#startShortcutActivity(ShortcutInfo, ActivityOptions, Rect)}
+ * </li>
+ *
+ * <li>The entry point for a root-task based task view is {@link
+ * TaskViewTaskController#startRootTask(ActivityManager.RunningTaskInfo, SurfaceControl,
+ * WindowContainerTransaction)}.
+ * This method is special as it doesn't create a root task and instead expects that the
+ * launch root task is already created and started. This method just attaches the taskInfo to
+ * the TaskView.
+ * </li>
+ * </ul>
*/
public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
@@ -155,8 +173,8 @@
* <p>The owner of this container must be allowed to access the shortcut information,
* as defined in {@link LauncherApps#hasShortcutHostPermission()} to use this method.
*
- * @param shortcut the shortcut used to launch the activity.
- * @param options options for the activity.
+ * @param shortcut the shortcut used to launch the activity.
+ * @param options options for the activity.
* @param launchBounds the bounds (window size and position) that the activity should be
* launched in, in pixels and in screen coordinates.
*/
@@ -183,10 +201,10 @@
* Launch a new activity.
*
* @param pendingIntent Intent used to launch an activity.
- * @param fillInIntent Additional Intent data, see {@link Intent#fillIn Intent.fillIn()}
- * @param options options for the activity.
- * @param launchBounds the bounds (window size and position) that the activity should be
- * launched in, in pixels and in screen coordinates.
+ * @param fillInIntent Additional Intent data, see {@link Intent#fillIn Intent.fillIn()}
+ * @param options options for the activity.
+ * @param launchBounds the bounds (window size and position) that the activity should be
+ * launched in, in pixels and in screen coordinates.
*/
public void startActivity(@NonNull PendingIntent pendingIntent, @Nullable Intent fillInIntent,
@NonNull ActivityOptions options, @Nullable Rect launchBounds) {
@@ -208,6 +226,35 @@
}
}
+
+ /**
+ * Attaches the given root task {@code taskInfo} in the task view.
+ *
+ * <p> Since {@link ShellTaskOrganizer#createRootTask(int, int,
+ * ShellTaskOrganizer.TaskListener)} does not use the shell transitions flow, this method is
+ * used as an entry point for an already-created root-task in the task view.
+ *
+ * @param taskInfo the task info of the root task.
+ * @param leash the {@link android.content.pm.ShortcutInfo.Surface} of the root task
+ * @param wct The Window container work that should happen as part of this set up.
+ */
+ public void startRootTask(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash,
+ @Nullable WindowContainerTransaction wct) {
+ if (wct == null) {
+ wct = new WindowContainerTransaction();
+ }
+ // This method skips the regular flow where an activity task is launched as part of a new
+ // transition in taskview and then transition is intercepted using the launchcookie.
+ // The task here is already created and running, it just needs to be reparented, resized
+ // and tracked correctly inside taskview. Which is done by calling
+ // prepareOpenAnimationInternal() and then manually enqueuing the resulting window container
+ // transaction.
+ prepareOpenAnimationInternal(true /* newTask */, mTransaction /* startTransaction */,
+ null /* finishTransaction */, taskInfo, leash, wct);
+ mTransaction.apply();
+ mTaskViewTransitions.startInstantTransition(TRANSIT_CHANGE, wct);
+ }
+
private void prepareActivityOptions(ActivityOptions options, Rect launchBounds) {
final Binder launchCookie = new Binder();
mShellExecutor.execute(() -> {
@@ -342,7 +389,6 @@
final SurfaceControl taskLeash = mTaskLeash;
handleAndNotifyTaskRemoval(mTaskInfo);
- // Unparent the task when this surface is destroyed
mTransaction.reparent(taskLeash, null).apply();
resetTaskInfo();
}
@@ -597,6 +643,15 @@
@NonNull SurfaceControl.Transaction finishTransaction,
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash,
WindowContainerTransaction wct) {
+ prepareOpenAnimationInternal(newTask, startTransaction, finishTransaction, taskInfo, leash,
+ wct);
+ }
+
+ private void prepareOpenAnimationInternal(final boolean newTask,
+ SurfaceControl.Transaction startTransaction,
+ SurfaceControl.Transaction finishTransaction,
+ ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash,
+ WindowContainerTransaction wct) {
mPendingInfo = null;
mTaskInfo = taskInfo;
mTaskToken = mTaskInfo.token;
@@ -608,10 +663,12 @@
// Also reparent on finishTransaction since the finishTransaction will reparent back
// to its "original" parent by default.
Rect boundsOnScreen = mTaskViewBase.getCurrentBoundsOnScreen();
- finishTransaction.reparent(mTaskLeash, mSurfaceControl)
- .setPosition(mTaskLeash, 0, 0)
- // TODO: maybe once b/280900002 is fixed this will be unnecessary
- .setWindowCrop(mTaskLeash, boundsOnScreen.width(), boundsOnScreen.height());
+ if (finishTransaction != null) {
+ finishTransaction.reparent(mTaskLeash, mSurfaceControl)
+ .setPosition(mTaskLeash, 0, 0)
+ // TODO: maybe once b/280900002 is fixed this will be unnecessary
+ .setWindowCrop(mTaskLeash, boundsOnScreen.width(), boundsOnScreen.height());
+ }
mTaskViewTransitions.updateBoundsState(this, boundsOnScreen);
mTaskViewTransitions.updateVisibilityState(this, true /* visible */);
wct.setBounds(mTaskToken, boundsOnScreen);
@@ -632,6 +689,7 @@
mTaskViewBase.setResizeBgColor(startTransaction, backgroundColor);
}
+ mTaskViewBase.onTaskAppeared(mTaskInfo, mTaskLeash);
if (mListener != null) {
final int taskId = mTaskInfo.taskId;
final ComponentName baseActivity = mTaskInfo.baseActivity;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
index 198ec82..e6d1b45 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTransitions.java
@@ -53,7 +53,7 @@
new ArrayMap<>();
private final ArrayList<PendingTransition> mPending = new ArrayList<>();
private final Transitions mTransitions;
- private final boolean[] mRegistered = new boolean[]{ false };
+ private final boolean[] mRegistered = new boolean[]{false};
/**
* TaskView makes heavy use of startTransition. Only one shell-initiated transition can be
@@ -122,6 +122,7 @@
/**
* Looks through the pending transitions for a closing transaction that matches the provided
* `taskView`.
+ *
* @param taskView the pending transition should be for this.
*/
private PendingTransition findPendingCloseTransition(TaskViewTaskController taskView) {
@@ -135,8 +136,17 @@
}
/**
+ * Starts a transition outside of the handler associated with {@link TaskViewTransitions}.
+ */
+ public void startInstantTransition(@WindowManager.TransitionType int type,
+ WindowContainerTransaction wct) {
+ mTransitions.startTransition(type, wct, null);
+ }
+
+ /**
* Looks through the pending transitions for a opening transaction that matches the provided
* `taskView`.
+ *
* @param taskView the pending transition should be for this.
*/
@VisibleForTesting
@@ -152,8 +162,9 @@
/**
* Looks through the pending transitions for one matching `taskView`.
+ *
* @param taskView the pending transition should be for this.
- * @param type the type of transition it's looking for
+ * @param type the type of transition it's looking for
*/
PendingTransition findPending(TaskViewTaskController taskView, int type) {
for (int i = mPending.size() - 1; i >= 0; --i) {
@@ -220,7 +231,24 @@
startNextTransition();
}
- void setTaskViewVisible(TaskViewTaskController taskView, boolean visible) {
+ /** Starts a new transition to make the given {@code taskView} visible. */
+ public void setTaskViewVisible(TaskViewTaskController taskView, boolean visible) {
+ setTaskViewVisible(taskView, visible, false /* reorder */);
+ }
+
+ /**
+ * Starts a new transition to make the given {@code taskView} visible and optionally change
+ * the task order.
+ *
+ * @param taskView the task view which the visibility is being changed for
+ * @param visible the new visibility of the task view
+ * @param reorder whether to reorder the task or not. If this is {@code true}, the task will be
+ * reordered as per the given {@code visible}. For {@code visible = true}, task
+ * will be reordered to top. For {@code visible = false}, task will be reordered
+ * to the bottom
+ */
+ public void setTaskViewVisible(TaskViewTaskController taskView, boolean visible,
+ boolean reorder) {
if (mTaskViews.get(taskView) == null) return;
if (mTaskViews.get(taskView).mVisible == visible) return;
if (taskView.getTaskInfo() == null) {
@@ -231,6 +259,9 @@
final WindowContainerTransaction wct = new WindowContainerTransaction();
wct.setHidden(taskView.getTaskInfo().token, !visible /* hidden */);
wct.setBounds(taskView.getTaskInfo().token, mTaskViews.get(taskView).mBounds);
+ if (reorder) {
+ wct.reorder(taskView.getTaskInfo().token, visible /* onTop */);
+ }
PendingTransition pending = new PendingTransition(
visible ? TRANSIT_TO_FRONT : TRANSIT_TO_BACK, wct, taskView, null /* cookie */);
mPending.add(pending);
@@ -238,6 +269,22 @@
// visibility is reported in transition.
}
+ /** Starts a new transition to reorder the given {@code taskView}'s task. */
+ public void reorderTaskViewTask(TaskViewTaskController taskView, boolean onTop) {
+ if (mTaskViews.get(taskView) == null) return;
+ if (taskView.getTaskInfo() == null) {
+ // Nothing to update, task is not yet available
+ return;
+ }
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.reorder(taskView.getTaskInfo().token, onTop /* onTop */);
+ PendingTransition pending = new PendingTransition(
+ onTop ? TRANSIT_TO_FRONT : TRANSIT_TO_BACK, wct, taskView, null /* cookie */);
+ mPending.add(pending);
+ startNextTransition();
+ // visibility is reported in transition.
+ }
+
void updateBoundsState(TaskViewTaskController taskView, Rect boundsOnScreen) {
TaskViewRequestedState state = mTaskViews.get(taskView);
if (state == null) return;
@@ -380,7 +427,7 @@
}
startTransaction.reparent(chg.getLeash(), tv.getSurfaceControl());
finishTransaction.reparent(chg.getLeash(), tv.getSurfaceControl())
- .setPosition(chg.getLeash(), 0, 0);
+ .setPosition(chg.getLeash(), 0, 0);
changesHandled++;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index 8746b8c..4bc0dc0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -61,9 +61,10 @@
/**
* A handler for dealing with transitions involving multiple other handlers. For example: an
- * activity in split-screen going into PiP.
+ * activity in split-screen going into PiP. Note this is provided as a handset-specific
+ * implementation of {@code MixedTransitionHandler}.
*/
-public class DefaultMixedHandler implements Transitions.TransitionHandler,
+public class DefaultMixedHandler implements MixedTransitionHandler,
RecentsTransitionHandler.RecentsMixedHandler {
private final Transitions mPlayer;
@@ -116,7 +117,7 @@
final IBinder mTransition;
protected final Transitions mPlayer;
- protected final DefaultMixedHandler mMixedHandler;
+ protected final MixedTransitionHandler mMixedHandler;
protected final PipTransitionController mPipHandler;
protected final StageCoordinator mSplitHandler;
protected final KeyguardTransitionHandler mKeyguardHandler;
@@ -142,7 +143,7 @@
int mInFlightSubAnimations = 0;
MixedTransition(int type, IBinder transition, Transitions player,
- DefaultMixedHandler mixedHandler, PipTransitionController pipHandler,
+ MixedTransitionHandler mixedHandler, PipTransitionController pipHandler,
StageCoordinator splitHandler, KeyguardTransitionHandler keyguardHandler) {
mType = type;
mTransition = transition;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java
index e9cd73b..b028bd6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedTransition.java
@@ -41,7 +41,7 @@
private final ActivityEmbeddingController mActivityEmbeddingController;
DefaultMixedTransition(int type, IBinder transition, Transitions player,
- DefaultMixedHandler mixedHandler, PipTransitionController pipHandler,
+ MixedTransitionHandler mixedHandler, PipTransitionController pipHandler,
StageCoordinator splitHandler, KeyguardTransitionHandler keyguardHandler,
UnfoldTransitionHandler unfoldHandler,
ActivityEmbeddingController activityEmbeddingController) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHandler.java
new file mode 100644
index 0000000..ff429fb
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHandler.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 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.wm.shell.transition;
+
+/**
+ * Interface for a {@link Transitions.TransitionHandler} that can take the subset of transitions
+ * that it handles and further decompose those transitions into sub-transitions which can be
+ * independently delegated to separate handlers.
+ */
+public interface MixedTransitionHandler extends Transitions.TransitionHandler {
+
+ // TODO(b/335685449) this currently exists purely as a marker interface for use in form-factor
+ // specific/sysui dagger modules. Going forward, we should define this in a meaningful
+ // way so as to provide a clear basis for expectations/behaviours associated with mixed
+ // transitions and their default handlers.
+
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java
index 0974cd1..ffc0b76 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/MixedTransitionHelper.java
@@ -44,7 +44,7 @@
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback,
- @NonNull Transitions player, @NonNull DefaultMixedHandler mixedHandler,
+ @NonNull Transitions player, @NonNull MixedTransitionHandler mixedHandler,
@NonNull PipTransitionController pipHandler, @NonNull StageCoordinator splitHandler) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Animating a mixed transition for "
+ "entering PIP while Split-Screen is foreground.");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java
index 5b402a5..d6e64cf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RecentsMixedTransition.java
@@ -43,7 +43,7 @@
private final DesktopTasksController mDesktopTasksController;
RecentsMixedTransition(int type, IBinder transition, Transitions player,
- DefaultMixedHandler mixedHandler, PipTransitionController pipHandler,
+ MixedTransitionHandler mixedHandler, PipTransitionController pipHandler,
StageCoordinator splitHandler, KeyguardTransitionHandler keyguardHandler,
RecentsTransitionHandler recentsHandler,
DesktopTasksController desktopTasksController) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/tracing/PerfettoTransitionTracer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/tracing/PerfettoTransitionTracer.java
index fa331af..ed4ae05 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/tracing/PerfettoTransitionTracer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/tracing/PerfettoTransitionTracer.java
@@ -16,7 +16,10 @@
package com.android.wm.shell.transition.tracing;
-import android.internal.perfetto.protos.PerfettoTrace;
+import android.internal.perfetto.protos.ShellTransitionOuterClass.ShellHandlerMapping;
+import android.internal.perfetto.protos.ShellTransitionOuterClass.ShellHandlerMappings;
+import android.internal.perfetto.protos.ShellTransitionOuterClass.ShellTransition;
+import android.internal.perfetto.protos.TracePacketOuterClass.TracePacket;
import android.os.SystemClock;
import android.os.Trace;
import android.tracing.perfetto.DataSourceParams;
@@ -72,11 +75,11 @@
final int handlerId = getHandlerId(handler);
final ProtoOutputStream os = ctx.newTracePacket();
- final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
- os.write(PerfettoTrace.ShellTransition.ID, transitionId);
- os.write(PerfettoTrace.ShellTransition.DISPATCH_TIME_NS,
+ final long token = os.start(TracePacket.SHELL_TRANSITION);
+ os.write(ShellTransition.ID, transitionId);
+ os.write(ShellTransition.DISPATCH_TIME_NS,
SystemClock.elapsedRealtimeNanos());
- os.write(PerfettoTrace.ShellTransition.HANDLER, handlerId);
+ os.write(ShellTransition.HANDLER, handlerId);
os.end(token);
});
}
@@ -117,11 +120,11 @@
private void doLogMergeRequested(int mergeRequestedTransitionId, int playingTransitionId) {
mDataSource.trace(ctx -> {
final ProtoOutputStream os = ctx.newTracePacket();
- final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
- os.write(PerfettoTrace.ShellTransition.ID, mergeRequestedTransitionId);
- os.write(PerfettoTrace.ShellTransition.MERGE_REQUEST_TIME_NS,
+ final long token = os.start(TracePacket.SHELL_TRANSITION);
+ os.write(ShellTransition.ID, mergeRequestedTransitionId);
+ os.write(ShellTransition.MERGE_REQUEST_TIME_NS,
SystemClock.elapsedRealtimeNanos());
- os.write(PerfettoTrace.ShellTransition.MERGE_TARGET, playingTransitionId);
+ os.write(ShellTransition.MERGE_TARGET, playingTransitionId);
os.end(token);
});
}
@@ -149,11 +152,11 @@
private void doLogMerged(int mergeRequestedTransitionId, int playingTransitionId) {
mDataSource.trace(ctx -> {
final ProtoOutputStream os = ctx.newTracePacket();
- final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
- os.write(PerfettoTrace.ShellTransition.ID, mergeRequestedTransitionId);
- os.write(PerfettoTrace.ShellTransition.MERGE_TIME_NS,
+ final long token = os.start(TracePacket.SHELL_TRANSITION);
+ os.write(ShellTransition.ID, mergeRequestedTransitionId);
+ os.write(ShellTransition.MERGE_TIME_NS,
SystemClock.elapsedRealtimeNanos());
- os.write(PerfettoTrace.ShellTransition.MERGE_TARGET, playingTransitionId);
+ os.write(ShellTransition.MERGE_TARGET, playingTransitionId);
os.end(token);
});
}
@@ -180,9 +183,9 @@
private void doLogAborted(int transitionId) {
mDataSource.trace(ctx -> {
final ProtoOutputStream os = ctx.newTracePacket();
- final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
- os.write(PerfettoTrace.ShellTransition.ID, transitionId);
- os.write(PerfettoTrace.ShellTransition.SHELL_ABORT_TIME_NS,
+ final long token = os.start(TracePacket.SHELL_TRANSITION);
+ os.write(ShellTransition.ID, transitionId);
+ os.write(ShellTransition.SHELL_ABORT_TIME_NS,
SystemClock.elapsedRealtimeNanos());
os.end(token);
});
@@ -196,14 +199,14 @@
mDataSource.trace(ctx -> {
final ProtoOutputStream os = ctx.newTracePacket();
- final long mappingsToken = os.start(PerfettoTrace.TracePacket.SHELL_HANDLER_MAPPINGS);
+ final long mappingsToken = os.start(TracePacket.SHELL_HANDLER_MAPPINGS);
for (Map.Entry<String, Integer> entry : mHandlerMapping.entrySet()) {
final String handler = entry.getKey();
final int handlerId = entry.getValue();
- final long mappingEntryToken = os.start(PerfettoTrace.ShellHandlerMappings.MAPPING);
- os.write(PerfettoTrace.ShellHandlerMapping.ID, handlerId);
- os.write(PerfettoTrace.ShellHandlerMapping.NAME, handler);
+ final long mappingEntryToken = os.start(ShellHandlerMappings.MAPPING);
+ os.write(ShellHandlerMapping.ID, handlerId);
+ os.write(ShellHandlerMapping.NAME, handler);
os.end(mappingEntryToken);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 777ab9c..6a9d17f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -1182,7 +1182,9 @@
final boolean inImmersiveMode = !source.isVisible();
// Calls WindowDecoration#relayout if decoration visibility needs to be updated
if (inImmersiveMode != mInImmersiveMode) {
- decor.relayout(decor.mTaskInfo);
+ if (Flags.enableDesktopWindowingImmersiveHandleHiding()) {
+ decor.relayout(decor.mTaskInfo);
+ }
mInImmersiveMode = inImmersiveMode;
}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/CloseAllAppWithAppHeaderExitLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/CloseAllAppWithAppHeaderExitLandscape.kt
new file mode 100644
index 0000000..5563bb9
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/CloseAllAppWithAppHeaderExitLandscape.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 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.wm.shell.flicker.service.desktopmode.flicker
+
+import android.tools.Rotation
+import android.tools.flicker.FlickerConfig
+import android.tools.flicker.annotation.ExpectedScenarios
+import android.tools.flicker.annotation.FlickerConfigProvider
+import android.tools.flicker.config.FlickerConfig
+import android.tools.flicker.config.FlickerServiceConfig
+import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
+import com.android.wm.shell.flicker.service.desktopmode.flicker.DesktopModeFlickerScenarios.Companion.CLOSE_APP
+import com.android.wm.shell.flicker.service.desktopmode.flicker.DesktopModeFlickerScenarios.Companion.CLOSE_LAST_APP
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.CloseAllAppsWithAppHeaderExit
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class CloseAllAppWithAppHeaderExitLandscape : CloseAllAppsWithAppHeaderExit(Rotation.ROTATION_90) {
+ @ExpectedScenarios(["CLOSE_APP", "CLOSE_LAST_APP"])
+ @Test
+ override fun closeAllAppsInDesktop() = super.closeAllAppsInDesktop()
+
+ companion object {
+ @JvmStatic
+ @FlickerConfigProvider
+ fun flickerConfigProvider(): FlickerConfig =
+ FlickerConfig()
+ .use(FlickerServiceConfig.DEFAULT)
+ .use(CLOSE_APP)
+ .use(CLOSE_LAST_APP)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/CloseAllAppWithAppHeaderExitPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/CloseAllAppWithAppHeaderExitPortrait.kt
new file mode 100644
index 0000000..3d16d2219
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/CloseAllAppWithAppHeaderExitPortrait.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 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.wm.shell.flicker.service.desktopmode.flicker
+
+import android.tools.Rotation
+import android.tools.flicker.FlickerConfig
+import android.tools.flicker.annotation.ExpectedScenarios
+import android.tools.flicker.annotation.FlickerConfigProvider
+import android.tools.flicker.config.FlickerConfig
+import android.tools.flicker.config.FlickerServiceConfig
+import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
+import com.android.wm.shell.flicker.service.desktopmode.flicker.DesktopModeFlickerScenarios.Companion.CLOSE_APP
+import com.android.wm.shell.flicker.service.desktopmode.flicker.DesktopModeFlickerScenarios.Companion.CLOSE_LAST_APP
+import com.android.wm.shell.flicker.service.desktopmode.scenarios.CloseAllAppsWithAppHeaderExit
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(FlickerServiceJUnit4ClassRunner::class)
+class CloseAllAppWithAppHeaderExitPortrait : CloseAllAppsWithAppHeaderExit(Rotation.ROTATION_0) {
+ @ExpectedScenarios(["CLOSE_APP", "CLOSE_LAST_APP"])
+ @Test
+ override fun closeAllAppsInDesktop() = super.closeAllAppsInDesktop()
+
+ companion object {
+ @JvmStatic
+ @FlickerConfigProvider
+ fun flickerConfigProvider(): FlickerConfig =
+ FlickerConfig()
+ .use(FlickerServiceConfig.DEFAULT)
+ .use(CLOSE_APP)
+ .use(CLOSE_LAST_APP)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/DesktopModeFlickerScenarios.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/DesktopModeFlickerScenarios.kt
new file mode 100644
index 0000000..75dfeba
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/DesktopModeFlickerScenarios.kt
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2024 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.wm.shell.flicker.service.desktopmode.flicker
+
+import android.tools.flicker.AssertionInvocationGroup
+import android.tools.flicker.assertors.assertions.AppLayerIsInvisibleAtEnd
+import android.tools.flicker.assertors.assertions.AppLayerIsVisibleAlways
+import android.tools.flicker.assertors.assertions.AppLayerIsVisibleAtStart
+import android.tools.flicker.assertors.assertions.AppWindowHasDesktopModeInitialBoundsAtTheEnd
+import android.tools.flicker.assertors.assertions.AppWindowOnTopAtEnd
+import android.tools.flicker.assertors.assertions.AppWindowOnTopAtStart
+import android.tools.flicker.assertors.assertions.LauncherWindowMovesToTop
+import android.tools.flicker.config.AssertionTemplates
+import android.tools.flicker.config.FlickerConfigEntry
+import android.tools.flicker.config.ScenarioId
+import android.tools.flicker.config.desktopmode.Components
+import android.tools.flicker.extractors.ITransitionMatcher
+import android.tools.flicker.extractors.ShellTransitionScenarioExtractor
+import android.tools.traces.wm.Transition
+import android.tools.traces.wm.TransitionType
+
+class DesktopModeFlickerScenarios {
+ companion object {
+ val END_DRAG_TO_DESKTOP =
+ FlickerConfigEntry(
+ scenarioId = ScenarioId("END_DRAG_TO_DESKTOP"),
+ extractor =
+ ShellTransitionScenarioExtractor(
+ transitionMatcher =
+ object : ITransitionMatcher {
+ override fun findAll(
+ transitions: Collection<Transition>
+ ): Collection<Transition> {
+ return transitions.filter {
+ it.type == TransitionType.DESKTOP_MODE_END_DRAG_TO_DESKTOP
+ }
+ }
+ }
+ ),
+ assertions =
+ AssertionTemplates.COMMON_ASSERTIONS +
+ listOf(
+ AppLayerIsVisibleAlways(Components.DESKTOP_MODE_APP),
+ AppWindowOnTopAtEnd(Components.DESKTOP_MODE_APP),
+ AppWindowHasDesktopModeInitialBoundsAtTheEnd(
+ Components.DESKTOP_MODE_APP
+ )
+ )
+ .associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
+ )
+
+ val CLOSE_APP =
+ FlickerConfigEntry(
+ scenarioId = ScenarioId("CLOSE_APP"),
+ extractor =
+ ShellTransitionScenarioExtractor(
+ transitionMatcher =
+ object : ITransitionMatcher {
+ override fun findAll(
+ transitions: Collection<Transition>
+ ): Collection<Transition> {
+ return transitions.filter { it.type == TransitionType.CLOSE }
+ }
+ }
+ ),
+ assertions =
+ AssertionTemplates.COMMON_ASSERTIONS +
+ listOf(
+ AppWindowOnTopAtStart(Components.DESKTOP_MODE_APP),
+ AppLayerIsVisibleAtStart(Components.DESKTOP_MODE_APP),
+ AppLayerIsInvisibleAtEnd(Components.DESKTOP_MODE_APP),
+ )
+ .associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
+ )
+
+ val CLOSE_LAST_APP =
+ FlickerConfigEntry(
+ scenarioId = ScenarioId("CLOSE_LAST_APP"),
+ extractor =
+ ShellTransitionScenarioExtractor(
+ transitionMatcher =
+ object : ITransitionMatcher {
+ override fun findAll(
+ transitions: Collection<Transition>
+ ): Collection<Transition> {
+ val lastTransition =
+ transitions.findLast { it.type == TransitionType.CLOSE }
+ return if (lastTransition != null) listOf(lastTransition)
+ else emptyList()
+ }
+ }
+ ),
+ assertions =
+ AssertionTemplates.COMMON_ASSERTIONS +
+ listOf(
+ AppWindowOnTopAtStart(Components.DESKTOP_MODE_APP),
+ AppLayerIsVisibleAtStart(Components.DESKTOP_MODE_APP),
+ AppLayerIsInvisibleAtEnd(Components.DESKTOP_MODE_APP),
+ LauncherWindowMovesToTop()
+ )
+ .associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
+ )
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/EnterDesktopWithDragLandscape.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/EnterDesktopWithDragLandscape.kt
index 4c781d3..9dfafe9 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/EnterDesktopWithDragLandscape.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/EnterDesktopWithDragLandscape.kt
@@ -17,58 +17,28 @@
package com.android.wm.shell.flicker.service.desktopmode.flicker
import android.tools.Rotation
-import android.tools.flicker.AssertionInvocationGroup
import android.tools.flicker.FlickerConfig
import android.tools.flicker.annotation.ExpectedScenarios
import android.tools.flicker.annotation.FlickerConfigProvider
-import android.tools.flicker.assertors.assertions.AppLayerIsVisibleAlways
-import android.tools.flicker.assertors.assertions.AppWindowHasDesktopModeInitialBoundsAtTheEnd
-import android.tools.flicker.assertors.assertions.AppWindowOnTopAtEnd
-import android.tools.flicker.config.AssertionTemplates
import android.tools.flicker.config.FlickerConfig
-import android.tools.flicker.config.FlickerConfigEntry
import android.tools.flicker.config.FlickerServiceConfig
-import android.tools.flicker.config.ScenarioId
-import android.tools.flicker.config.desktopmode.Components
-import android.tools.flicker.extractors.ITransitionMatcher
-import android.tools.flicker.extractors.ShellTransitionScenarioExtractor
import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
-import android.tools.traces.wm.Transition
-import android.tools.traces.wm.TransitionType
+import com.android.wm.shell.flicker.service.desktopmode.flicker.DesktopModeFlickerScenarios.Companion.END_DRAG_TO_DESKTOP
import com.android.wm.shell.flicker.service.desktopmode.scenarios.EnterDesktopWithDrag
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(FlickerServiceJUnit4ClassRunner::class)
class EnterDesktopWithDragLandscape : EnterDesktopWithDrag(Rotation.ROTATION_90) {
- @ExpectedScenarios(["END_DRAG_TO_DESKTOP"]) @Test override fun enterDesktopWithDrag() =
- super.enterDesktopWithDrag()
+ @ExpectedScenarios(["END_DRAG_TO_DESKTOP"])
+ @Test
+ override fun enterDesktopWithDrag() = super.enterDesktopWithDrag()
companion object {
- private val END_DRAG_TO_DESKTOP = FlickerConfigEntry(
- scenarioId = ScenarioId("END_DRAG_TO_DESKTOP"),
- extractor = ShellTransitionScenarioExtractor(
- transitionMatcher = object : ITransitionMatcher {
- override fun findAll(
- transitions: Collection<Transition>
- ): Collection<Transition> {
- return transitions.filter {
- it.type == TransitionType.DESKTOP_MODE_END_DRAG_TO_DESKTOP}
- }
- }),
- assertions = AssertionTemplates.COMMON_ASSERTIONS +
- listOf(
- AppLayerIsVisibleAlways(Components.DESKTOP_MODE_APP),
- AppWindowOnTopAtEnd(Components.DESKTOP_MODE_APP),
- AppWindowHasDesktopModeInitialBoundsAtTheEnd(Components.DESKTOP_MODE_APP)
- ).associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
- )
@JvmStatic
@FlickerConfigProvider
fun flickerConfigProvider(): FlickerConfig =
- FlickerConfig()
- .use(FlickerServiceConfig.DEFAULT)
- .use(END_DRAG_TO_DESKTOP)
+ FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(END_DRAG_TO_DESKTOP)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/EnterDesktopWithDragPortrait.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/EnterDesktopWithDragPortrait.kt
index d99d875..1c7d623 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/EnterDesktopWithDragPortrait.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/flicker/EnterDesktopWithDragPortrait.kt
@@ -17,58 +17,27 @@
package com.android.wm.shell.flicker.service.desktopmode.flicker
import android.tools.Rotation
-import android.tools.flicker.AssertionInvocationGroup
import android.tools.flicker.FlickerConfig
import android.tools.flicker.annotation.ExpectedScenarios
import android.tools.flicker.annotation.FlickerConfigProvider
-import android.tools.flicker.assertors.assertions.AppLayerIsVisibleAlways
-import android.tools.flicker.assertors.assertions.AppWindowHasDesktopModeInitialBoundsAtTheEnd
-import android.tools.flicker.assertors.assertions.AppWindowOnTopAtEnd
-import android.tools.flicker.config.AssertionTemplates
import android.tools.flicker.config.FlickerConfig
-import android.tools.flicker.config.FlickerConfigEntry
import android.tools.flicker.config.FlickerServiceConfig
-import android.tools.flicker.config.ScenarioId
-import android.tools.flicker.config.desktopmode.Components
-import android.tools.flicker.extractors.ITransitionMatcher
-import android.tools.flicker.extractors.ShellTransitionScenarioExtractor
import android.tools.flicker.junit.FlickerServiceJUnit4ClassRunner
-import android.tools.traces.wm.Transition
-import android.tools.traces.wm.TransitionType
+import com.android.wm.shell.flicker.service.desktopmode.flicker.DesktopModeFlickerScenarios.Companion.END_DRAG_TO_DESKTOP
import com.android.wm.shell.flicker.service.desktopmode.scenarios.EnterDesktopWithDrag
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(FlickerServiceJUnit4ClassRunner::class)
class EnterDesktopWithDragPortrait : EnterDesktopWithDrag(Rotation.ROTATION_0) {
- @ExpectedScenarios(["END_DRAG_TO_DESKTOP"]) @Test override fun enterDesktopWithDrag() =
- super.enterDesktopWithDrag()
+ @ExpectedScenarios(["END_DRAG_TO_DESKTOP"])
+ @Test
+ override fun enterDesktopWithDrag() = super.enterDesktopWithDrag()
companion object {
- private val END_DRAG_TO_DESKTOP = FlickerConfigEntry(
- scenarioId = ScenarioId("END_DRAG_TO_DESKTOP"),
- extractor = ShellTransitionScenarioExtractor(
- transitionMatcher = object : ITransitionMatcher {
- override fun findAll(
- transitions: Collection<Transition>
- ): Collection<Transition> {
- return transitions.filter {
- it.type == TransitionType.DESKTOP_MODE_END_DRAG_TO_DESKTOP}
- }
- }),
- assertions = AssertionTemplates.COMMON_ASSERTIONS +
- listOf(
- AppLayerIsVisibleAlways(Components.DESKTOP_MODE_APP),
- AppWindowOnTopAtEnd(Components.DESKTOP_MODE_APP),
- AppWindowHasDesktopModeInitialBoundsAtTheEnd(Components.DESKTOP_MODE_APP)
- ).associateBy({ it }, { AssertionInvocationGroup.BLOCKING }),
- )
-
@JvmStatic
@FlickerConfigProvider
fun flickerConfigProvider(): FlickerConfig =
- FlickerConfig()
- .use(FlickerServiceConfig.DEFAULT)
- .use(END_DRAG_TO_DESKTOP)
+ FlickerConfig().use(FlickerServiceConfig.DEFAULT).use(END_DRAG_TO_DESKTOP)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/CloseAllAppsWithAppHeaderExit.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/CloseAllAppsWithAppHeaderExit.kt
new file mode 100644
index 0000000..0c2b501
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/CloseAllAppsWithAppHeaderExit.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 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.wm.shell.flicker.service.desktopmode.scenarios
+
+import android.app.Instrumentation
+import android.tools.NavBar
+import android.tools.Rotation
+import android.tools.traces.parsers.WindowManagerStateHelper
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.DesktopModeAppHelper
+import com.android.server.wm.flicker.helpers.MailAppHelper
+import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
+import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.window.flags.Flags
+import com.android.wm.shell.flicker.service.common.Utils
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+
+@Ignore("Base Test Class")
+abstract class CloseAllAppsWithAppHeaderExit
+@JvmOverloads
+constructor(val rotation: Rotation = Rotation.ROTATION_0) {
+
+ private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val tapl = LauncherInstrumentation()
+ private val wmHelper = WindowManagerStateHelper(instrumentation)
+ private val device = UiDevice.getInstance(instrumentation)
+ private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation))
+ private val mailApp = DesktopModeAppHelper(MailAppHelper(instrumentation))
+ private val nonResizeableApp = DesktopModeAppHelper(NonResizeableAppHelper(instrumentation))
+
+
+
+ @Rule @JvmField val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation)
+
+ @Before
+ fun setup() {
+ Assume.assumeTrue(Flags.enableDesktopWindowingMode())
+ tapl.setEnableRotation(true)
+ tapl.setExpectedRotation(rotation.value)
+ testApp.enterDesktopWithDrag(wmHelper, device)
+ mailApp.launchViaIntent(wmHelper)
+ nonResizeableApp.launchViaIntent(wmHelper)
+ }
+
+ @Test
+ open fun closeAllAppsInDesktop() {
+ nonResizeableApp.closeDesktopApp(wmHelper, device)
+ mailApp.closeDesktopApp(wmHelper, device)
+ testApp.closeDesktopApp(wmHelper, device)
+ }
+
+ @After
+ fun teardown() {
+ testApp.exit(wmHelper)
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/EnterDesktopWithDrag.kt b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/EnterDesktopWithDrag.kt
index 0403b4f..9e9998e 100644
--- a/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/EnterDesktopWithDrag.kt
+++ b/libs/WindowManager/Shell/tests/flicker/service/src/com/android/wm/shell/flicker/service/desktopmode/scenarios/EnterDesktopWithDrag.kt
@@ -23,15 +23,18 @@
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.helpers.DesktopModeAppHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.window.flags.Flags
import com.android.wm.shell.flicker.service.common.Utils
-import com.android.wm.shell.flicker.utils.DesktopModeUtils
import org.junit.After
+import org.junit.Assume
import org.junit.Before
import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
+
@Ignore("Base Test Class")
abstract class EnterDesktopWithDrag
@JvmOverloads
@@ -41,19 +44,20 @@
private val tapl = LauncherInstrumentation()
private val wmHelper = WindowManagerStateHelper(instrumentation)
private val device = UiDevice.getInstance(instrumentation)
- private val testApp = SimpleAppHelper(instrumentation)
+ private val testApp = DesktopModeAppHelper(SimpleAppHelper(instrumentation))
@Rule @JvmField val testSetupRule = Utils.testSetupRule(NavBar.MODE_GESTURAL, rotation)
@Before
fun setup() {
+ Assume.assumeTrue(Flags.enableDesktopWindowingMode())
tapl.setEnableRotation(true)
tapl.setExpectedRotation(rotation.value)
}
@Test
open fun enterDesktopWithDrag() {
- DesktopModeUtils.enterDesktopWithDrag(wmHelper, device, testApp)
+ testApp.enterDesktopWithDrag(wmHelper, device)
}
@After
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/DesktopModeUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/DesktopModeUtils.kt
deleted file mode 100644
index 345bc5e..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/utils/DesktopModeUtils.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2024 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.wm.shell.flicker.utils
-
-import android.tools.device.apphelpers.StandardAppHelper
-import android.tools.helpers.SYSTEMUI_PACKAGE
-import android.tools.traces.component.IComponentMatcher
-import android.tools.traces.parsers.WindowManagerStateHelper
-import android.tools.traces.wm.WindowingMode
-import androidx.test.uiautomator.By
-import androidx.test.uiautomator.BySelector
-import androidx.test.uiautomator.UiDevice
-import androidx.test.uiautomator.Until
-
-/**
- * Provides a collection of utility functions for desktop mode testing.
- */
-object DesktopModeUtils {
- private const val TIMEOUT_MS = 3_000L
- private const val CAPTION = "desktop_mode_caption"
- private const val CAPTION_HANDLE = "caption_handle"
- private const val MAXIMIZE_BUTTON = "maximize_button_view"
-
- private val captionFullscreen: BySelector
- get() = By.res(SYSTEMUI_PACKAGE, CAPTION)
- private val captionHandle: BySelector
- get() = By.res(SYSTEMUI_PACKAGE, CAPTION_HANDLE)
- private val maximizeButton: BySelector
- get() = By.res(SYSTEMUI_PACKAGE, MAXIMIZE_BUTTON)
-
- /**
- * Wait for an app moved to desktop to finish its transition.
- */
- private fun waitForAppToMoveToDesktop(
- wmHelper: WindowManagerStateHelper,
- currentApp: IComponentMatcher,
- ) {
- wmHelper
- .StateSyncBuilder()
- .withWindowSurfaceAppeared(currentApp)
- .withFreeformApp(currentApp)
- .withAppTransitionIdle()
- .waitForAndVerify()
- }
-
- /**
- * Click maximise button on the app header for the given app.
- */
- fun maximiseDesktopApp(
- wmHelper: WindowManagerStateHelper,
- device: UiDevice,
- currentApp: StandardAppHelper
- ) {
- if (wmHelper.getWindow(currentApp)?.windowingMode
- != WindowingMode.WINDOWING_MODE_FREEFORM.value)
- error("expected a freeform window to maximise but window is not in freefrom mode")
-
- val maximizeButton =
- device.wait(Until.findObject(maximizeButton), TIMEOUT_MS)
- ?: error("Unable to find view $maximizeButton\n")
- maximizeButton.click()
- }
-
- /**
- * Move an app to Desktop by dragging the app handle at the top.
- */
- fun enterDesktopWithDrag(
- wmHelper: WindowManagerStateHelper,
- device: UiDevice,
- currentApp: StandardAppHelper,
- ) {
- currentApp.launchViaIntent(wmHelper)
- dragToDesktop(wmHelper, currentApp, device)
- waitForAppToMoveToDesktop(wmHelper, currentApp)
- }
-
- private fun dragToDesktop(
- wmHelper: WindowManagerStateHelper,
- currentApp: StandardAppHelper,
- device: UiDevice
- ) {
- val windowRect = wmHelper.getWindowRegion(currentApp).bounds
- val startX = windowRect.centerX()
-
- // Start dragging a little under the top to prevent dragging the notification shade.
- val startY = 10
-
- val displayRect =
- wmHelper.currentState.wmState.getDefaultDisplay()?.displayRect
- ?: throw IllegalStateException("Default display is null")
-
- // The position we want to drag to
- val endY = displayRect.centerY() / 2
-
- // drag the window to move to desktop
- device.drag(startX, startY, startX, endY, 100)
- }
-}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
index d7c4610..0434742 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTest.java
@@ -44,7 +44,6 @@
import android.graphics.Insets;
import android.graphics.Rect;
import android.graphics.Region;
-import android.os.Handler;
import android.os.Looper;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -498,6 +497,31 @@
}
@Test
+ public void testStartRootTask_setsBoundsAndVisibility() {
+ assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
+
+ TaskViewBase taskViewBase = mock(TaskViewBase.class);
+ Rect bounds = new Rect(0, 0, 100, 100);
+ when(taskViewBase.getCurrentBoundsOnScreen()).thenReturn(bounds);
+ mTaskViewTaskController.setTaskViewBase(taskViewBase);
+
+ // Surface created, but task not available so bounds / visibility isn't set
+ mTaskView.surfaceCreated(mock(SurfaceHolder.class));
+ verify(mTaskViewTransitions, never()).updateVisibilityState(
+ eq(mTaskViewTaskController), eq(true));
+
+ // Make the task available
+ WindowContainerTransaction wct = mock(WindowContainerTransaction.class);
+ mTaskViewTaskController.startRootTask(mTaskInfo, mLeash, wct);
+
+ // Bounds got set
+ verify(wct).setBounds(any(WindowContainerToken.class), eq(bounds));
+ // Visibility & bounds state got set
+ verify(mTaskViewTransitions).updateVisibilityState(eq(mTaskViewTaskController), eq(true));
+ verify(mTaskViewTransitions).updateBoundsState(eq(mTaskViewTaskController), eq(bounds));
+ }
+
+ @Test
public void testTaskViewPrepareOpenAnimationSetsBoundsAndVisibility() {
assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionsTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionsTest.java
index fbc0db9..d3e40f2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionsTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/taskview/TaskViewTransitionsTest.java
@@ -18,6 +18,7 @@
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static com.google.common.truth.Truth.assertThat;
@@ -208,6 +209,48 @@
}
@Test
+ public void testReorderTask_movedToFrontTransaction() {
+ assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
+
+ mTaskViewTransitions.reorderTaskViewTask(mTaskViewTaskController, true);
+ // Consume the pending transaction from order change
+ TaskViewTransitions.PendingTransition pending =
+ mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_TO_FRONT);
+ assertThat(pending).isNotNull();
+ mTaskViewTransitions.startAnimation(pending.mClaimed,
+ mock(TransitionInfo.class),
+ new SurfaceControl.Transaction(),
+ new SurfaceControl.Transaction(),
+ mock(Transitions.TransitionFinishCallback.class));
+
+ // Verify it was consumed
+ TaskViewTransitions.PendingTransition pending2 =
+ mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_TO_FRONT);
+ assertThat(pending2).isNull();
+ }
+
+ @Test
+ public void testReorderTask_movedToBackTransaction() {
+ assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
+
+ mTaskViewTransitions.reorderTaskViewTask(mTaskViewTaskController, false);
+ // Consume the pending transaction from order change
+ TaskViewTransitions.PendingTransition pending =
+ mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_TO_BACK);
+ assertThat(pending).isNotNull();
+ mTaskViewTransitions.startAnimation(pending.mClaimed,
+ mock(TransitionInfo.class),
+ new SurfaceControl.Transaction(),
+ new SurfaceControl.Transaction(),
+ mock(Transitions.TransitionFinishCallback.class));
+
+ // Verify it was consumed
+ TaskViewTransitions.PendingTransition pending2 =
+ mTaskViewTransitions.findPending(mTaskViewTaskController, TRANSIT_TO_BACK);
+ assertThat(pending2).isNull();
+ }
+
+ @Test
public void test_startAnimation_setsTaskNotFound() {
assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
index 8e9619d..7d19f3c 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
@@ -28,6 +28,9 @@
import android.hardware.display.VirtualDisplay
import android.os.Handler
import android.platform.test.annotations.EnableFlags
+import android.platform.test.annotations.RequiresFlagsEnabled
+import android.platform.test.flag.junit.CheckFlagsRule
+import android.platform.test.flag.junit.DeviceFlagsValueProvider
import android.platform.test.flag.junit.SetFlagsRule
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
@@ -97,6 +100,10 @@
@Rule
val setFlagsRule = SetFlagsRule()
+ @JvmField
+ @Rule
+ val mCheckFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
+
@Mock private lateinit var mockDesktopModeWindowDecorFactory:
DesktopModeWindowDecoration.Factory
@Mock private lateinit var mockMainHandler: Handler
@@ -306,6 +313,7 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_IMMERSIVE_HANDLE_HIDING)
fun testRelayoutRunsWhenStatusBarsInsetsSourceVisibilityChanges() {
val task = createTask(windowingMode = WINDOWING_MODE_FREEFORM, focused = true)
val decoration = setUpMockDecorationForTask(task)
@@ -326,6 +334,7 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_IMMERSIVE_HANDLE_HIDING)
fun testRelayoutDoesNotRunWhenNonStatusBarsInsetsSourceVisibilityChanges() {
val task = createTask(windowingMode = WINDOWING_MODE_FREEFORM, focused = true)
val decoration = setUpMockDecorationForTask(task)
@@ -346,6 +355,7 @@
}
@Test
+ @RequiresFlagsEnabled(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_IMMERSIVE_HANDLE_HIDING)
fun testRelayoutDoesNotRunWhenNonStatusBarsInsetSourceVisibilityDoesNotChange() {
val task = createTask(windowingMode = WINDOWING_MODE_FREEFORM, focused = true)
val decoration = setUpMockDecorationForTask(task)
diff --git a/libs/hostgraphics/HostBufferQueue.cpp b/libs/hostgraphics/HostBufferQueue.cpp
index ec30437..b4fd5d9 100644
--- a/libs/hostgraphics/HostBufferQueue.cpp
+++ b/libs/hostgraphics/HostBufferQueue.cpp
@@ -16,12 +16,15 @@
#include <gui/BufferQueue.h>
+#include <system/window.h>
+
namespace android {
class HostBufferQueue : public IGraphicBufferProducer, public IGraphicBufferConsumer {
public:
HostBufferQueue() : mWidth(0), mHeight(0) { }
+// Consumer
virtual status_t setConsumerIsProtected(bool isProtected) { return OK; }
virtual status_t detachBuffer(int slot) { return OK; }
@@ -51,6 +54,28 @@
virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) { return OK; }
virtual status_t setConsumerUsageBits(uint64_t usage) { return OK; }
+
+// Producer
+ virtual int query(int what, int* value) {
+ switch(what) {
+ case NATIVE_WINDOW_WIDTH:
+ *value = mWidth;
+ break;
+ case NATIVE_WINDOW_HEIGHT:
+ *value = mHeight;
+ break;
+ default:
+ *value = 0;
+ break;
+ }
+ return OK;
+ }
+
+ virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) {
+ *buf = mBuffer;
+ return OK;
+ }
+
private:
sp<GraphicBuffer> mBuffer;
uint32_t mWidth;
diff --git a/libs/hostgraphics/gui/IGraphicBufferProducer.h b/libs/hostgraphics/gui/IGraphicBufferProducer.h
index a1efd0b..1447a4f 100644
--- a/libs/hostgraphics/gui/IGraphicBufferProducer.h
+++ b/libs/hostgraphics/gui/IGraphicBufferProducer.h
@@ -31,6 +31,10 @@
// Disconnect any API originally connected from the process calling disconnect.
AllLocal
};
+
+ virtual int query(int what, int* value) = 0;
+
+ virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) = 0;
};
} // namespace android
diff --git a/libs/hostgraphics/gui/Surface.h b/libs/hostgraphics/gui/Surface.h
index 36d8fba..0d81037 100644
--- a/libs/hostgraphics/gui/Surface.h
+++ b/libs/hostgraphics/gui/Surface.h
@@ -17,18 +17,21 @@
#ifndef ANDROID_GUI_SURFACE_H
#define ANDROID_GUI_SURFACE_H
-#include <gui/IGraphicBufferProducer.h>
+#include <system/window.h>
#include <ui/ANativeObjectBase.h>
#include <utils/RefBase.h>
-#include <system/window.h>
+
+#include "gui/IGraphicBufferProducer.h"
namespace android {
class Surface : public ANativeObjectBase<ANativeWindow, Surface, RefBase> {
public:
- explicit Surface(const sp<IGraphicBufferProducer>& bufferProducer,
- bool controlledByApp = false) {
+ explicit Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp = false)
+ : mBufferProducer(bufferProducer) {
ANativeWindow::perform = hook_perform;
+ ANativeWindow::dequeueBuffer = hook_dequeueBuffer;
+ ANativeWindow::query = hook_query;
}
static bool isValid(const sp<Surface>& surface) { return surface != nullptr; }
void allocateBuffers() {}
@@ -48,7 +51,11 @@
return 0;
}
virtual int unlockAndPost() { return 0; }
- virtual int query(int what, int* value) const { return 0; }
+ virtual int query(int what, int* value) const { return mBufferProducer->query(what, value); }
+
+ status_t setDequeueTimeout(nsecs_t timeout) { return OK; }
+
+ nsecs_t getLastDequeueStartTime() const { return 0; }
virtual void destroy() {}
@@ -57,12 +64,44 @@
protected:
virtual ~Surface() {}
- static int hook_perform(ANativeWindow* window, int operation, ...) { return 0; }
+ static int hook_perform(ANativeWindow* window, int operation, ...) {
+ va_list args;
+ va_start(args, operation);
+ Surface* c = getSelf(window);
+ int result = c->perform(operation, args);
+ va_end(args);
+ return result;
+ }
+
+ static int hook_query(const ANativeWindow* window, int what, int* value) {
+ const Surface* c = getSelf(window);
+ return c->query(what, value);
+ }
+
+ static int hook_dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer,
+ int* fenceFd) {
+ Surface* c = getSelf(window);
+ return c->dequeueBuffer(buffer, fenceFd);
+ }
+
+ virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd) {
+ mBufferProducer->requestBuffer(0, &mBuffer);
+ *buffer = mBuffer.get();
+ return OK;
+ }
+ virtual int cancelBuffer(ANativeWindowBuffer* buffer, int fenceFd) { return 0; }
+ virtual int queueBuffer(ANativeWindowBuffer* buffer, int fenceFd) { return 0; }
+ virtual int perform(int operation, va_list args) { return 0; }
+ virtual int setSwapInterval(int interval) { return 0; }
+ virtual int setBufferCount(int bufferCount) { return 0; }
private:
// can't be copied
Surface& operator=(const Surface& rhs);
Surface(const Surface& rhs);
+
+ const sp<IGraphicBufferProducer> mBufferProducer;
+ sp<GraphicBuffer> mBuffer;
};
} // namespace android
diff --git a/libs/hostgraphics/ui/GraphicBuffer.h b/libs/hostgraphics/ui/GraphicBuffer.h
index ac88e44..eec9b23 100644
--- a/libs/hostgraphics/ui/GraphicBuffer.h
+++ b/libs/hostgraphics/ui/GraphicBuffer.h
@@ -22,24 +22,27 @@
#include <vector>
+#include <ui/ANativeObjectBase.h>
#include <ui/PixelFormat.h>
#include <ui/Rect.h>
-
#include <utils/RefBase.h>
namespace android {
-class GraphicBuffer : virtual public RefBase {
+class GraphicBuffer : public ANativeObjectBase<ANativeWindowBuffer, GraphicBuffer, RefBase> {
public:
- GraphicBuffer(uint32_t w, uint32_t h):width(w),height(h) {
+ GraphicBuffer(uint32_t w, uint32_t h) {
data.resize(w*h);
+ reserved[0] = data.data();
+ width = w;
+ height = h;
}
uint32_t getWidth() const { return static_cast<uint32_t>(width); }
uint32_t getHeight() const { return static_cast<uint32_t>(height); }
uint32_t getStride() const { return static_cast<uint32_t>(width); }
uint64_t getUsage() const { return 0; }
PixelFormat getPixelFormat() const { return PIXEL_FORMAT_RGBA_8888; }
- //uint32_t getLayerCount() const { return static_cast<uint32_t>(layerCount); }
+
Rect getBounds() const { return Rect(width, height); }
status_t lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,
@@ -54,8 +57,6 @@
status_t unlockAsync(int *fenceFd) { return OK; }
private:
- uint32_t width;
- uint32_t height;
std::vector<uint32_t> data;
};
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index b870023..8e07a2f 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -15,14 +15,18 @@
*/
#include "ShaderCache.h"
+
#include <GrDirectContext.h>
#include <SkData.h>
#include <gui/TraceUtils.h>
#include <log/log.h>
#include <openssl/sha.h>
+
#include <algorithm>
#include <array>
+#include <mutex>
#include <thread>
+
#include "FileBlobCache.h"
#include "Properties.h"
diff --git a/libs/hwui/renderthread/HintSessionWrapper.cpp b/libs/hwui/renderthread/HintSessionWrapper.cpp
index 6993d52..7a155c5 100644
--- a/libs/hwui/renderthread/HintSessionWrapper.cpp
+++ b/libs/hwui/renderthread/HintSessionWrapper.cpp
@@ -45,7 +45,7 @@
LOG_ALWAYS_FATAL_IF(handle_ == nullptr, "Failed to dlopen libandroid.so!");
BIND_APH_METHOD(getManager);
- BIND_APH_METHOD(createSession);
+ BIND_APH_METHOD(createSessionInternal);
BIND_APH_METHOD(closeSession);
BIND_APH_METHOD(updateTargetWorkDuration);
BIND_APH_METHOD(reportActualWorkDuration);
@@ -122,7 +122,8 @@
int64_t targetDurationNanos =
mLastTargetWorkDuration == 0 ? kDefaultTargetDuration : mLastTargetWorkDuration;
mHintSessionFuture = CommonPool::async([=, this, tids = mPermanentSessionTids] {
- return mBinding->createSession(manager, tids.data(), tids.size(), targetDurationNanos);
+ return mBinding->createSessionInternal(manager, tids.data(), tids.size(),
+ targetDurationNanos, SessionTag::HWUI);
});
return false;
}
diff --git a/libs/hwui/renderthread/HintSessionWrapper.h b/libs/hwui/renderthread/HintSessionWrapper.h
index 14e7a53..859cc57 100644
--- a/libs/hwui/renderthread/HintSessionWrapper.h
+++ b/libs/hwui/renderthread/HintSessionWrapper.h
@@ -17,6 +17,7 @@
#pragma once
#include <android/performance_hint.h>
+#include <private/performance_hint_private.h>
#include <future>
#include <optional>
@@ -80,9 +81,10 @@
virtual ~HintSessionBinding() = default;
virtual void init();
APerformanceHintManager* (*getManager)();
- APerformanceHintSession* (*createSession)(APerformanceHintManager* manager,
- const int32_t* tids, size_t tidCount,
- int64_t defaultTarget) = nullptr;
+ APerformanceHintSession* (*createSessionInternal)(APerformanceHintManager* manager,
+ const int32_t* tids, size_t tidCount,
+ int64_t defaultTarget,
+ SessionTag tag) = nullptr;
void (*closeSession)(APerformanceHintSession* session) = nullptr;
void (*updateTargetWorkDuration)(APerformanceHintSession* session,
int64_t targetDuration) = nullptr;
diff --git a/libs/hwui/tests/unit/HintSessionWrapperTests.cpp b/libs/hwui/tests/unit/HintSessionWrapperTests.cpp
index c16602c..a8db0f4 100644
--- a/libs/hwui/tests/unit/HintSessionWrapperTests.cpp
+++ b/libs/hwui/tests/unit/HintSessionWrapperTests.cpp
@@ -52,8 +52,8 @@
void init() override;
MOCK_METHOD(APerformanceHintManager*, fakeGetManager, ());
- MOCK_METHOD(APerformanceHintSession*, fakeCreateSession,
- (APerformanceHintManager*, const int32_t*, size_t, int64_t));
+ MOCK_METHOD(APerformanceHintSession*, fakeCreateSessionInternal,
+ (APerformanceHintManager*, const int32_t*, size_t, int64_t, SessionTag));
MOCK_METHOD(void, fakeCloseSession, (APerformanceHintSession*));
MOCK_METHOD(void, fakeUpdateTargetWorkDuration, (APerformanceHintSession*, int64_t));
MOCK_METHOD(void, fakeReportActualWorkDuration, (APerformanceHintSession*, int64_t));
@@ -72,22 +72,28 @@
// Must be static so we can point to them as normal fn pointers with HintSessionBinding
static APerformanceHintManager* stubGetManager() { return sMockBinding->fakeGetManager(); };
- static APerformanceHintSession* stubCreateSession(APerformanceHintManager* manager,
- const int32_t* ids, size_t idsSize,
- int64_t initialTarget) {
- return sMockBinding->fakeCreateSession(manager, ids, idsSize, initialTarget);
+ static APerformanceHintSession* stubCreateSessionInternal(APerformanceHintManager* manager,
+ const int32_t* ids, size_t idsSize,
+ int64_t initialTarget,
+ SessionTag tag) {
+ return sMockBinding->fakeCreateSessionInternal(manager, ids, idsSize, initialTarget,
+ SessionTag::HWUI);
}
- static APerformanceHintSession* stubManagedCreateSession(APerformanceHintManager* manager,
- const int32_t* ids, size_t idsSize,
- int64_t initialTarget) {
+ static APerformanceHintSession* stubManagedCreateSessionInternal(
+ APerformanceHintManager* manager, const int32_t* ids, size_t idsSize,
+ int64_t initialTarget, SessionTag tag) {
sMockBinding->allowCreationToFinish.get_future().wait();
- return sMockBinding->fakeCreateSession(manager, ids, idsSize, initialTarget);
+ return sMockBinding->fakeCreateSessionInternal(manager, ids, idsSize, initialTarget,
+ SessionTag::HWUI);
}
- static APerformanceHintSession* stubSlowCreateSession(APerformanceHintManager* manager,
- const int32_t* ids, size_t idsSize,
- int64_t initialTarget) {
+ static APerformanceHintSession* stubSlowCreateSessionInternal(APerformanceHintManager* manager,
+ const int32_t* ids,
+ size_t idsSize,
+ int64_t initialTarget,
+ SessionTag tag) {
std::this_thread::sleep_for(50ms);
- return sMockBinding->fakeCreateSession(manager, ids, idsSize, initialTarget);
+ return sMockBinding->fakeCreateSessionInternal(manager, ids, idsSize, initialTarget,
+ SessionTag::HWUI);
}
static void stubCloseSession(APerformanceHintSession* session) {
sMockBinding->fakeCloseSession(session);
@@ -139,14 +145,14 @@
mWrapper = std::make_shared<HintSessionWrapper>(uiThreadId, renderThreadId);
mWrapper->mBinding = sMockBinding;
EXPECT_CALL(*sMockBinding, fakeGetManager).WillOnce(Return(managerPtr));
- ON_CALL(*sMockBinding, fakeCreateSession).WillByDefault(Return(sessionPtr));
+ ON_CALL(*sMockBinding, fakeCreateSessionInternal).WillByDefault(Return(sessionPtr));
ON_CALL(*sMockBinding, fakeSetThreads).WillByDefault(Return(0));
}
void HintSessionWrapperTests::MockHintSessionBinding::init() {
sMockBinding->getManager = &stubGetManager;
- if (sMockBinding->createSession == nullptr) {
- sMockBinding->createSession = &stubCreateSession;
+ if (sMockBinding->createSessionInternal == nullptr) {
+ sMockBinding->createSessionInternal = &stubCreateSessionInternal;
}
sMockBinding->closeSession = &stubCloseSession;
sMockBinding->updateTargetWorkDuration = &stubUpdateTargetWorkDuration;
@@ -163,14 +169,14 @@
TEST_F(HintSessionWrapperTests, destructorClosesBackgroundSession) {
EXPECT_CALL(*sMockBinding, fakeCloseSession(sessionPtr)).Times(1);
- sMockBinding->createSession = stubSlowCreateSession;
+ sMockBinding->createSessionInternal = stubSlowCreateSessionInternal;
mWrapper->init();
mWrapper = nullptr;
Mock::VerifyAndClearExpectations(sMockBinding.get());
}
TEST_F(HintSessionWrapperTests, sessionInitializesCorrectly) {
- EXPECT_CALL(*sMockBinding, fakeCreateSession(managerPtr, _, Gt(1), _)).Times(1);
+ EXPECT_CALL(*sMockBinding, fakeCreateSessionInternal(managerPtr, _, Gt(1), _, _)).Times(1);
mWrapper->init();
waitForWrapperReady();
}
@@ -219,7 +225,7 @@
// Here we test whether queueing delayedDestroy works while creation is still happening, if
// creation happens after
EXPECT_CALL(*sMockBinding, fakeCloseSession(sessionPtr)).Times(1);
- sMockBinding->createSession = &stubManagedCreateSession;
+ sMockBinding->createSessionInternal = &stubManagedCreateSessionInternal;
// Start creating the session and destroying it at the same time
mWrapper->init();
@@ -246,7 +252,7 @@
// Here we test whether queueing delayedDestroy works while creation is still happening, if
// creation happens before
EXPECT_CALL(*sMockBinding, fakeCloseSession(sessionPtr)).Times(1);
- sMockBinding->createSession = &stubManagedCreateSession;
+ sMockBinding->createSessionInternal = &stubManagedCreateSessionInternal;
// Start creating the session and destroying it at the same time
mWrapper->init();
@@ -352,7 +358,7 @@
}
TEST_F(HintSessionWrapperTests, setThreadsUpdatesSessionThreads) {
- EXPECT_CALL(*sMockBinding, fakeCreateSession(managerPtr, _, Gt(1), _)).Times(1);
+ EXPECT_CALL(*sMockBinding, fakeCreateSessionInternal(managerPtr, _, Gt(1), _, _)).Times(1);
EXPECT_CALL(*sMockBinding, fakeSetThreads(sessionPtr, testing::IsSupersetOf({11, 22})))
.Times(1);
mWrapper->init();
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index c664d3d..ffd6e16 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -545,16 +545,17 @@
? SCANNING_STATE_SCANNING_FULL
: SCANNING_STATE_WHILE_INTERACTIVE);
- if (scanRequest.isScreenOffScan()) {
- mScreenOffScanRequestCount++;
- } else {
- mScreenOnScanRequestCount++;
- }
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
+ if (scanRequest.isScreenOffScan()) {
+ mScreenOffScanRequestCount++;
+ } else {
+ mScreenOnScanRequestCount++;
+ }
+
mScanRequestsMap.put(token.mId, scanRequest);
return token;
}
@@ -580,27 +581,29 @@
}
boolean shouldUpdate =
- mScreenOffScanRequestCount == 1
- && (request.isScreenOffScan() || mScreenOnScanRequestCount == 1);
+ request.isScreenOffScan()
+ ? mScreenOffScanRequestCount == 1
+ : mScreenOnScanRequestCount == 1 && mScreenOffScanRequestCount == 0;
if (shouldUpdate) {
try {
- if (request.isScreenOffScan() && mScreenOnScanRequestCount == 0) {
+ if (!request.isScreenOffScan() || mScreenOnScanRequestCount == 0) {
mImpl.updateScanningState(SCANNING_STATE_NOT_SCANNING);
} else {
mImpl.updateScanningState(SCANNING_STATE_WHILE_INTERACTIVE);
}
- if (request.isScreenOffScan()) {
- mScreenOffScanRequestCount--;
- } else {
- mScreenOnScanRequestCount--;
- }
} catch (RemoteException ex) {
ex.rethrowFromSystemServer();
}
}
+ if (request.isScreenOffScan()) {
+ mScreenOffScanRequestCount--;
+ } else {
+ mScreenOnScanRequestCount--;
+ }
+
mScanRequestsMap.remove(token.mId);
}
}
diff --git a/media/java/android/media/RoutingSessionInfo.java b/media/java/android/media/RoutingSessionInfo.java
index 2202766..a3c8b68 100644
--- a/media/java/android/media/RoutingSessionInfo.java
+++ b/media/java/android/media/RoutingSessionInfo.java
@@ -84,7 +84,6 @@
*
* @hide
*/
- @FlaggedApi(FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_SUITABILITY_STATUSES)
@IntDef(value = {TRANSFER_REASON_FALLBACK, TRANSFER_REASON_SYSTEM_REQUEST, TRANSFER_REASON_APP})
@Retention(RetentionPolicy.SOURCE)
public @interface TransferReason {}
@@ -382,14 +381,12 @@
}
/** @hide */
- @FlaggedApi(FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_SUITABILITY_STATUSES)
@Nullable
public UserHandle getTransferInitiatorUserHandle() {
return mTransferInitiatorUserHandle;
}
/** @hide */
- @FlaggedApi(FLAG_ENABLE_BUILT_IN_SPEAKER_ROUTE_SUITABILITY_STATUSES)
@Nullable
public String getTransferInitiatorPackageName() {
return mTransferInitiatorPackageName;
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 8a13c03..4492c85 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -2088,28 +2088,24 @@
}
return BAD_VALUE;
}
- size_t offset = static_cast<size_t>(env->GetIntField(param, gFields.bufferInfoOffset));
- size_t size = static_cast<size_t>(env->GetIntField(param, gFields.bufferInfoSize));
+ ssize_t offset = static_cast<ssize_t>(env->GetIntField(param, gFields.bufferInfoOffset));
+ ssize_t size = static_cast<ssize_t>(env->GetIntField(param, gFields.bufferInfoSize));
uint32_t flags = static_cast<uint32_t>(env->GetIntField(param, gFields.bufferInfoFlags));
- if (flags == 0 && size == 0) {
+ if (i == 0) {
+ *initialOffset = offset;
+ }
+ if (CC_UNLIKELY((offset < 0)
+ || (size < 0)
+ || ((INT32_MAX - offset) < size)
+ || ((offset - (*initialOffset)) != *totalSize))) {
if (errorDetailMsg) {
- *errorDetailMsg = "Error: Queuing an empty BufferInfo";
+ *errorDetailMsg = "Error: offset/size in BufferInfo";
}
return BAD_VALUE;
}
- if (i == 0) {
- *initialOffset = offset;
- if (CC_UNLIKELY(*initialOffset < 0)) {
- if (errorDetailMsg) {
- *errorDetailMsg = "Error: offset/size in BufferInfo";
- }
- return BAD_VALUE;
- }
- }
- if (CC_UNLIKELY(((ssize_t)(UINT32_MAX - offset) < (ssize_t)size)
- || ((offset - *initialOffset) != *totalSize))) {
+ if (flags == 0 && size == 0) {
if (errorDetailMsg) {
- *errorDetailMsg = "Error: offset/size in BufferInfo";
+ *errorDetailMsg = "Error: Queuing an empty BufferInfo";
}
return BAD_VALUE;
}
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 1c203e3..346c87d 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -366,6 +366,7 @@
APerformanceHint_setIHintManagerForTesting;
APerformanceHint_sendHint;
APerformanceHint_getThreadIds;
+ APerformanceHint_createSessionInternal;
extern "C++" {
ASurfaceControl_registerSurfaceStatsListener*;
ASurfaceControl_unregisterSurfaceStatsListener*;
diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp
index fbb35e2..83056b2 100644
--- a/native/android/performance_hint.cpp
+++ b/native/android/performance_hint.cpp
@@ -463,6 +463,15 @@
return manager->createSession(threadIds, size, initialTargetWorkDurationNanos);
}
+APerformanceHintSession* APerformanceHint_createSessionInternal(
+ APerformanceHintManager* manager, const int32_t* threadIds, size_t size,
+ int64_t initialTargetWorkDurationNanos, SessionTag tag) {
+ VALIDATE_PTR(manager)
+ VALIDATE_PTR(threadIds)
+ return manager->createSession(threadIds, size, initialTargetWorkDurationNanos,
+ static_cast<hal::SessionTag>(tag));
+}
+
int64_t APerformanceHint_getPreferredUpdateRateNanos(APerformanceHintManager* manager) {
VALIDATE_PTR(manager)
return manager->getPreferredRateNanos();
@@ -486,9 +495,9 @@
delete session;
}
-int APerformanceHint_sendHint(void* session, SessionHint hint) {
+int APerformanceHint_sendHint(APerformanceHintSession* session, SessionHint hint) {
VALIDATE_PTR(session)
- return reinterpret_cast<APerformanceHintSession*>(session)->sendHint(hint);
+ return session->sendHint(hint);
}
int APerformanceHint_setThreads(APerformanceHintSession* session, const pid_t* threadIds,
@@ -498,11 +507,10 @@
return session->setThreads(threadIds, size);
}
-int APerformanceHint_getThreadIds(void* aPerformanceHintSession, int32_t* const threadIds,
+int APerformanceHint_getThreadIds(APerformanceHintSession* session, int32_t* const threadIds,
size_t* const size) {
- VALIDATE_PTR(aPerformanceHintSession)
- return static_cast<APerformanceHintSession*>(aPerformanceHintSession)
- ->getThreadIds(threadIds, size);
+ VALIDATE_PTR(session)
+ return session->getThreadIds(threadIds, size);
}
int APerformanceHint_setPreferPowerEfficiency(APerformanceHintSession* session, bool enabled) {
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
index 974e6e6..58f56b8 100644
--- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -30,9 +30,7 @@
#include <memory>
#include <vector>
-using aidl::android::hardware::power::SessionConfig;
-using aidl::android::hardware::power::SessionTag;
-using aidl::android::hardware::power::WorkDuration;
+namespace hal = aidl::android::hardware::power;
using aidl::android::os::IHintManager;
using aidl::android::os::IHintSession;
using ndk::ScopedAStatus;
@@ -45,7 +43,7 @@
public:
MOCK_METHOD(ScopedAStatus, createHintSessionWithConfig,
(const SpAIBinder& token, const ::std::vector<int32_t>& tids, int64_t durationNanos,
- SessionTag tag, std::optional<SessionConfig>* config,
+ hal::SessionTag tag, std::optional<hal::SessionConfig>* config,
std::shared_ptr<IHintSession>* _aidl_return),
(override));
MOCK_METHOD(ScopedAStatus, getHintSessionPreferredRate, (int64_t * _aidl_return), (override));
@@ -71,7 +69,7 @@
MOCK_METHOD(ScopedAStatus, setMode, (int32_t mode, bool enabled), (override));
MOCK_METHOD(ScopedAStatus, close, (), (override));
MOCK_METHOD(ScopedAStatus, reportActualWorkDuration2,
- (const ::std::vector<WorkDuration>& workDurations), (override));
+ (const ::std::vector<hal::WorkDuration>& workDurations), (override));
MOCK_METHOD(SpAIBinder, asBinder, (), (override));
MOCK_METHOD(bool, isRemote, (), (override));
};
@@ -95,7 +93,7 @@
return APerformanceHint_getManager();
}
APerformanceHintSession* createSession(APerformanceHintManager* manager,
- int64_t targetDuration = 56789L) {
+ int64_t targetDuration = 56789L, bool isHwui = false) {
mMockSession = ndk::SharedRefBase::make<NiceMock<MockIHintSession>>();
int64_t sessionId = 123;
std::vector<int32_t> tids;
@@ -104,8 +102,8 @@
ON_CALL(*mMockIHintManager,
createHintSessionWithConfig(_, Eq(tids), Eq(targetDuration), _, _, _))
- .WillByDefault(DoAll(SetArgPointee<4>(
- std::make_optional<SessionConfig>({.id = sessionId})),
+ .WillByDefault(DoAll(SetArgPointee<4>(std::make_optional<hal::SessionConfig>(
+ {.id = sessionId})),
SetArgPointee<5>(std::shared_ptr<IHintSession>(mMockSession)),
[] { return ScopedAStatus::ok(); }));
@@ -124,6 +122,10 @@
ON_CALL(*mMockSession, reportActualWorkDuration2(_)).WillByDefault([] {
return ScopedAStatus::ok();
});
+ if (isHwui) {
+ return APerformanceHint_createSessionInternal(manager, tids.data(), tids.size(),
+ targetDuration, SessionTag::HWUI);
+ }
return APerformanceHint_createSession(manager, tids.data(), tids.size(), targetDuration);
}
@@ -131,7 +133,7 @@
std::shared_ptr<NiceMock<MockIHintSession>> mMockSession = nullptr;
};
-bool equalsWithoutTimestamp(WorkDuration lhs, WorkDuration rhs) {
+bool equalsWithoutTimestamp(hal::WorkDuration lhs, hal::WorkDuration rhs) {
return lhs.workPeriodStartTimestampNanos == rhs.workPeriodStartTimestampNanos &&
lhs.cpuDurationNanos == rhs.cpuDurationNanos &&
lhs.gpuDurationNanos == rhs.gpuDurationNanos && lhs.durationNanos == rhs.durationNanos;
@@ -194,6 +196,16 @@
APerformanceHint_closeSession(session);
}
+TEST_F(PerformanceHintTest, TestHwuiSessionCreation) {
+ EXPECT_CALL(*mMockIHintManager,
+ createHintSessionWithConfig(_, _, _, hal::SessionTag::HWUI, _, _))
+ .Times(1);
+ APerformanceHintManager* manager = createManager();
+ APerformanceHintSession* session = createSession(manager, 56789L, true);
+ ASSERT_TRUE(session);
+ APerformanceHint_closeSession(session);
+}
+
TEST_F(PerformanceHintTest, SetThreads) {
APerformanceHintManager* manager = createManager();
@@ -249,8 +261,8 @@
return false;
}
for (int i = 0; i < expected.size(); ++i) {
- WorkDuration expectedWorkDuration = expected[i];
- WorkDuration actualWorkDuration = arg[i];
+ hal::WorkDuration expectedWorkDuration = expected[i];
+ hal::WorkDuration actualWorkDuration = arg[i];
if (!equalsWithoutTimestamp(expectedWorkDuration, actualWorkDuration)) {
*result_listener << "WorkDuration at [" << i << "] is different: "
<< "Expected: " << expectedWorkDuration.toString()
@@ -273,7 +285,7 @@
usleep(2); // Sleep for longer than preferredUpdateRateNanos.
struct TestPair {
- WorkDuration duration;
+ hal::WorkDuration duration;
int expectedResult;
};
std::vector<TestPair> testPairs{
@@ -282,7 +294,7 @@
{{1, -20, 1, 13, -8}, EINVAL},
};
for (auto&& pair : testPairs) {
- std::vector<WorkDuration> actualWorkDurations;
+ std::vector<hal::WorkDuration> actualWorkDurations;
actualWorkDurations.push_back(pair.duration);
EXPECT_CALL(*mMockSession, reportActualWorkDuration2(WorkDurationEq(actualWorkDurations)))
diff --git a/packages/CrashRecovery/aconfig/flags.aconfig b/packages/CrashRecovery/aconfig/flags.aconfig
index cddbb6b..8cdef38 100644
--- a/packages/CrashRecovery/aconfig/flags.aconfig
+++ b/packages/CrashRecovery/aconfig/flags.aconfig
@@ -16,3 +16,11 @@
description: "Enables various dependencies of crashrecovery module"
bug: "289203818"
}
+
+flag {
+ name: "allow_rescue_party_flag_resets"
+ namespace: "crashrecovery"
+ description: "Enables rescue party flag resets"
+ bug: "287618292"
+ is_fixed_read_only: true
+}
diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
index bf69d3b..4437475 100644
--- a/packages/PackageInstaller/AndroidManifest.xml
+++ b/packages/PackageInstaller/AndroidManifest.xml
@@ -23,6 +23,7 @@
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
+ <uses-permission android:name="android.permission.READ_SYSTEM_GRAMMATICAL_GENDER" />
<uses-permission android:name="com.google.android.permission.INSTALL_WEARABLE_PACKAGES" />
diff --git a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_arrow_drop_down.xml b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_arrow_drop_down.xml
index 77979f0..8755247 100644
--- a/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_arrow_drop_down.xml
+++ b/packages/SettingsLib/SettingsTheme/res/drawable-v35/settingslib_arrow_drop_down.xml
@@ -16,11 +16,12 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:viewportWidth="18"
- android:viewportHeight="18"
- android:width="24dp"
- android:height="24dp">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="@color/settingslib_materialColorOnPrimaryContainer">
<path
- android:pathData="M7 10l5 5 5 -5z"
- android:fillColor="@color/settingslib_materialColorOnPrimaryContainer"/>
+ android:fillColor="@android:color/white"
+ android:pathData="M16.59,8.59L12,13.17 7.41,8.59 6,10l6,6 6,-6 -1.41,-1.41z"/>
</vector>
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/SpaDialogWindowTypeActivity.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/SpaDialogWindowTypeActivity.kt
index 46975f5..fb9e98e 100644
--- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/SpaDialogWindowTypeActivity.kt
+++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/SpaDialogWindowTypeActivity.kt
@@ -47,7 +47,7 @@
super.finish()
}
- abstract val dialogWindowType: Int?
+ abstract fun getDialogWindowType(): Int?
@Composable
abstract fun Content()
@@ -67,7 +67,7 @@
}
override fun onCreate(savedInstanceState: Bundle?) {
- dialogWindowType?.let { window?.setType(it) }
+ getDialogWindowType()?.let { window?.setType(it) }
super.onCreate(savedInstanceState)
}
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/database/ContentChangeFlow.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/database/ContentChangeFlow.kt
index 8f67354..7ea4b18 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/database/ContentChangeFlow.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/database/ContentChangeFlow.kt
@@ -27,7 +27,7 @@
import kotlinx.coroutines.flow.flowOn
/** Content change flow for the given [uri]. */
-internal fun Context.contentChangeFlow(
+fun Context.contentChangeFlow(
uri: Uri,
sendInitial: Boolean = true,
): Flow<Unit> = callbackFlow {
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index a67839a..73c96d9 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -200,6 +200,10 @@
<string name="bluetooth_active_battery_level">Active. <xliff:g id="battery_level_as_percentage">%1$s</xliff:g> battery.</string>
<!-- Connected devices settings. Message when Bluetooth is connected and active, showing remote device status and battery level for untethered headset. [CHAR LIMIT=NONE] -->
<string name="bluetooth_active_battery_level_untethered">Active. L: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g>, R: <xliff:g id="battery_level_as_percentage" example="25%">%2$s</xliff:g> battery.</string>
+ <!-- Connected devices settings. Message when Bluetooth is connected and active, showing remote device status and battery level for the left part of the untethered headset. [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_active_battery_level_untethered_left">Active. L: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery</string>
+ <!-- Connected devices settings. Message when Bluetooth is connected and active, showing remote device status and battery level for the right part of the untethered headset. [CHAR LIMIT=NONE] -->
+ <string name="bluetooth_active_battery_level_untethered_right">Active. R: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery</string>
<!-- Connected devices settings. Message when Bluetooth is connected but not in use, showing remote device battery level. [CHAR LIMIT=NONE] -->
<string name="bluetooth_battery_level"><xliff:g id="battery_level_as_percentage">%1$s</xliff:g> battery</string>
<!-- Connected devices settings. Message on TV when Bluetooth is connected but not in use, showing remote device battery level. [CHAR LIMIT=NONE] -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/accounts/AuthenticatorHelper.java b/packages/SettingsLib/src/com/android/settingslib/accounts/AuthenticatorHelper.java
index 4af9e3c..2f6d839 100644
--- a/packages/SettingsLib/src/com/android/settingslib/accounts/AuthenticatorHelper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/accounts/AuthenticatorHelper.java
@@ -106,8 +106,7 @@
AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
Context authContext = context.createPackageContextAsUser(desc.packageName, 0,
mUserHandle);
- icon = mContext.getPackageManager().getUserBadgedIcon(
- authContext.getDrawable(desc.iconId), mUserHandle);
+ icon = authContext.getDrawable(desc.iconId);
synchronized (mAccTypeIconCache) {
mAccTypeIconCache.put(accountType, icon);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 36a9ecf..a7b7da5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -1476,30 +1476,13 @@
}
}
- // Try to show left/right information if can not get it from battery for hearing
+ // Try to show left/right information for hearing
// aids specifically.
boolean isActiveAshaHearingAid = mIsActiveDeviceHearingAid;
boolean isActiveLeAudioHearingAid = mIsActiveDeviceLeAudio
&& isConnectedHapClientDevice();
if (isActiveAshaHearingAid || isActiveLeAudioHearingAid) {
- final Set<CachedBluetoothDevice> memberDevices = getMemberDevice();
- final CachedBluetoothDevice subDevice = getSubDevice();
- if (memberDevices.stream().anyMatch(m -> m.isConnected())) {
- stringRes = R.string.bluetooth_hearing_aid_left_and_right_active;
- } else if (subDevice != null && subDevice.isConnected()) {
- stringRes = R.string.bluetooth_hearing_aid_left_and_right_active;
- } else {
- int deviceSide = getDeviceSide();
- if (deviceSide == HearingAidInfo.DeviceSide.SIDE_LEFT_AND_RIGHT) {
- stringRes = R.string.bluetooth_hearing_aid_left_and_right_active;
- } else if (deviceSide == HearingAidInfo.DeviceSide.SIDE_LEFT) {
- stringRes = R.string.bluetooth_hearing_aid_left_active;
- } else if (deviceSide == HearingAidInfo.DeviceSide.SIDE_RIGHT) {
- stringRes = R.string.bluetooth_hearing_aid_right_active;
- } else {
- stringRes = R.string.bluetooth_active_no_battery_level;
- }
- }
+ return getHearingDeviceSummary(leftBattery, rightBattery, shortSummary);
}
}
}
@@ -1567,6 +1550,62 @@
return spannableBuilder;
}
+ private CharSequence getHearingDeviceSummary(int leftBattery, int rightBattery,
+ boolean shortSummary) {
+
+ CachedBluetoothDevice memberDevice = getMemberDevice().stream().filter(
+ CachedBluetoothDevice::isConnected).findFirst().orElse(null);
+ if (memberDevice == null && mSubDevice != null && mSubDevice.isConnected()) {
+ memberDevice = mSubDevice;
+ }
+
+ CachedBluetoothDevice leftDevice = null;
+ CachedBluetoothDevice rightDevice = null;
+ final int deviceSide = getDeviceSide();
+ if (deviceSide == HearingAidInfo.DeviceSide.SIDE_LEFT) {
+ leftDevice = this;
+ rightDevice = memberDevice;
+ } else if (deviceSide == HearingAidInfo.DeviceSide.SIDE_RIGHT) {
+ leftDevice = memberDevice;
+ rightDevice = this;
+ } else if (deviceSide == HearingAidInfo.DeviceSide.SIDE_LEFT_AND_RIGHT) {
+ leftDevice = this;
+ rightDevice = this;
+ }
+
+ if (leftBattery < 0 && leftDevice != null) {
+ leftBattery = leftDevice.getBatteryLevel();
+ }
+ if (rightBattery < 0 && rightDevice != null) {
+ rightBattery = rightDevice.getBatteryLevel();
+ }
+
+ if (leftDevice != null && rightDevice != null) {
+ if (leftBattery >= 0 && rightBattery >= 0 && !shortSummary) {
+ return mContext.getString(R.string.bluetooth_active_battery_level_untethered,
+ Utils.formatPercentage(leftBattery), Utils.formatPercentage(rightBattery));
+ } else {
+ return mContext.getString(R.string.bluetooth_hearing_aid_left_and_right_active);
+ }
+ } else if (leftDevice != null) {
+ if (leftBattery >= 0 && !shortSummary) {
+ return mContext.getString(R.string.bluetooth_active_battery_level_untethered_left,
+ Utils.formatPercentage(leftBattery));
+ } else {
+ return mContext.getString(R.string.bluetooth_hearing_aid_left_active);
+ }
+ } else if (rightDevice != null) {
+ if (rightBattery >= 0 && !shortSummary) {
+ return mContext.getString(R.string.bluetooth_active_battery_level_untethered_right,
+ Utils.formatPercentage(rightBattery));
+ } else {
+ return mContext.getString(R.string.bluetooth_hearing_aid_right_active);
+ }
+ }
+
+ return mContext.getString(R.string.bluetooth_active_no_battery_level);
+ }
+
private void addBatterySpan(SpannableStringBuilder builder,
String batteryString, boolean lowBattery, int lowBatteryColorRes) {
if (lowBattery && lowBatteryColorRes != SUMMARY_NO_COLOR_FOR_LOW_BATTERY) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt
index d5444cf..727c61c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.kt
@@ -28,19 +28,21 @@
import android.os.Bundle
import android.os.SystemClock
import android.util.Log
+import android.view.WindowManager
import androidx.annotation.VisibleForTesting
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.android.settingslib.R
import com.android.settingslib.flags.Flags.newStatusBarIcons
-import java.util.Locale
-import kotlin.coroutines.resume
+import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
import kotlinx.coroutines.asExecutor
import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
-
+import java.util.Locale
+import kotlin.coroutines.resume
open class WifiUtils {
/**
@@ -473,9 +475,28 @@
context: Context,
lifecycleOwner: LifecycleOwner,
ssid: String,
- onAllowed: () -> Unit,
+ onAllowed: () -> Unit
) {
- lifecycleOwner.lifecycleScope.launch {
+ checkWepAllowed(
+ context,
+ lifecycleOwner.lifecycleScope,
+ ssid,
+ WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW,
+ { intent -> context.startActivity(intent) },
+ onAllowed
+ )
+ }
+
+ @JvmStatic
+ fun checkWepAllowed(
+ context: Context,
+ coroutineScope: CoroutineScope,
+ ssid: String,
+ dialogWindowType: Int,
+ onStartActivity: (intent: Intent) -> Unit,
+ onAllowed: () -> Unit,
+ ): Job =
+ coroutineScope.launch {
val wifiManager = context.getSystemService(WifiManager::class.java) ?: return@launch
if (wifiManager.queryWepAllowed()) {
onAllowed()
@@ -485,12 +506,12 @@
"com.android.settings",
"com.android.settings.network.WepNetworkDialogActivity"
)
+ putExtra(DIALOG_WINDOW_TYPE, dialogWindowType)
putExtra(SSID, ssid)
- }
- context.startActivity(intent)
+ }.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ onStartActivity(intent)
}
}
- }
private suspend fun WifiManager.queryWepAllowed(): Boolean =
withContext(Dispatchers.Default) {
@@ -502,5 +523,6 @@
}
const val SSID = "ssid"
+ const val DIALOG_WINDOW_TYPE = "dialog_window_type"
}
}
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 892d907..e2af631 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -169,7 +169,6 @@
"androidx.compose.material_material-icons-extended",
"androidx.activity_activity-compose",
"androidx.compose.animation_animation-graphics",
- "androidx.test.rules",
],
libs: [
"keepanno-annotations",
@@ -192,6 +191,7 @@
lint: {
extra_check_modules: ["SystemUILintChecker"],
warning_checks: ["MissingApacheLicenseDetector"],
+ baseline_filename: "lint-baseline.xml",
},
}
@@ -426,6 +426,7 @@
kotlincflags: ["-Xjvm-default=all"],
optimize: {
shrink_resources: false,
+ optimized_shrink_resources: false,
proguard_flags_files: ["proguard.flags"],
},
@@ -515,6 +516,7 @@
optimize: true,
shrink: true,
shrink_resources: true,
+ optimized_shrink_resources: true,
ignore_warnings: false,
proguard_compatibility: false,
},
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 561c85e..5cc3caf 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -1036,6 +1036,7 @@
<receiver
android:name=".statusbar.KeyboardShortcutsReceiver"
+ android:visibleToInstantApps="true"
android:exported="true">
<intent-filter>
<action android:name="com.android.intent.action.DISMISS_KEYBOARD_SHORTCUTS" />
@@ -1116,5 +1117,11 @@
android:name="android.service.dream"
android:resource="@xml/home_controls_dream_metadata" />
</service>
+
+ <activity android:name="com.android.systemui.keyboard.shortcut.ShortcutHelperActivity"
+ android:exported="false"
+ android:theme="@style/ShortcutHelperTheme"
+ android:excludeFromRecents="true"
+ android:finishOnCloseSystemDialogs="true" />
</application>
</manifest>
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 16bc7f2..fadef1e 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -497,7 +497,7 @@
}
flag {
- name: "screenshot_shelf_ui"
+ name: "screenshot_shelf_ui2"
namespace: "systemui"
description: "Use new shelf UI flow for screenshots"
bug: "329659738"
@@ -776,6 +776,13 @@
}
flag {
+ name: "keyboard_shortcut_helper_rewrite"
+ namespace: "systemui"
+ description: "A new implementation of the keyboards shortcuts helper sheet."
+ bug: "327364197"
+}
+
+flag {
name: "dream_overlay_bouncer_swipe_direction_filtering"
namespace: "systemui"
description: "do not initiate bouncer swipe when the direction is opposite of the expansion"
@@ -814,3 +821,10 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "enforce_brightness_base_user_restriction"
+ namespace: "systemui"
+ description: "Enforce BaseUserRestriction for DISALLOW_CONFIG_BRIGHTNESS."
+ bug: "329205638"
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt
index 9ce30fd..1e60b98 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt
@@ -599,6 +599,12 @@
)
}
+ init {
+ // We do this check here to cover all entry points, including Launcher which doesn't
+ // call startIntentWithAnimation()
+ if (!controller.isLaunching) TransitionAnimator.checkReturnAnimationFrameworkFlag()
+ }
+
@UiThread
internal fun postTimeouts() {
if (timeoutHandler != null) {
@@ -637,7 +643,28 @@
return
}
- startAnimation(apps, nonApps, callback)
+ val window = findRootTaskIfPossible(apps)
+ if (window == null) {
+ Log.i(TAG, "Aborting the animation as no window is opening")
+ callback?.invoke()
+
+ if (DEBUG_TRANSITION_ANIMATION) {
+ Log.d(
+ TAG,
+ "Calling controller.onTransitionAnimationCancelled() [no window opening]"
+ )
+ }
+ controller.onTransitionAnimationCancelled()
+ listener?.onTransitionAnimationCancelled()
+ return
+ }
+
+ val navigationBar =
+ nonApps?.firstOrNull {
+ it.windowType == WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
+ }
+
+ startAnimation(window, navigationBar, callback)
}
private fun findRootTaskIfPossible(
@@ -646,9 +673,17 @@
if (apps == null) {
return null
}
+
+ val targetMode =
+ if (controller.isLaunching) {
+ RemoteAnimationTarget.MODE_OPENING
+ } else {
+ RemoteAnimationTarget.MODE_CLOSING
+ }
var candidate: RemoteAnimationTarget? = null
+
for (it in apps) {
- if (it.mode == RemoteAnimationTarget.MODE_OPENING) {
+ if (it.mode == targetMode) {
if (activityTransitionUseLargestWindow()) {
if (
candidate == null ||
@@ -673,47 +708,31 @@
}
}
}
+
return candidate
}
private fun startAnimation(
- apps: Array<out RemoteAnimationTarget>?,
- nonApps: Array<out RemoteAnimationTarget>?,
+ window: RemoteAnimationTarget,
+ navigationBar: RemoteAnimationTarget?,
iCallback: IRemoteAnimationFinishedCallback?
) {
if (TransitionAnimator.DEBUG) {
Log.d(TAG, "Remote animation started")
}
- val window = findRootTaskIfPossible(apps)
- if (window == null) {
- Log.i(TAG, "Aborting the animation as no window is opening")
- iCallback?.invoke()
-
- if (DEBUG_TRANSITION_ANIMATION) {
- Log.d(
- TAG,
- "Calling controller.onTransitionAnimationCancelled() [no window opening]"
- )
- }
- controller.onTransitionAnimationCancelled()
- listener?.onTransitionAnimationCancelled()
- return
- }
-
- val navigationBar =
- nonApps?.firstOrNull {
- it.windowType == WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
- }
-
val windowBounds = window.screenSpaceBounds
val endState =
- TransitionAnimator.State(
- top = windowBounds.top,
- bottom = windowBounds.bottom,
- left = windowBounds.left,
- right = windowBounds.right
- )
+ if (controller.isLaunching) {
+ TransitionAnimator.State(
+ top = windowBounds.top,
+ bottom = windowBounds.bottom,
+ left = windowBounds.left,
+ right = windowBounds.right
+ )
+ } else {
+ controller.createAnimatorState()
+ }
val windowBackgroundColor =
window.taskInfo?.let { callback.getBackgroundColor(it) } ?: window.backgroundColor
@@ -721,24 +740,29 @@
// instead of recomputing isExpandingFullyAbove here.
val isExpandingFullyAbove =
transitionAnimator.isExpandingFullyAbove(controller.transitionContainer, endState)
- val endRadius =
- if (isExpandingFullyAbove) {
- // Most of the time, expanding fully above the root view means expanding in full
- // screen.
- ScreenDecorationsUtils.getWindowCornerRadius(context)
- } else {
- // This usually means we are in split screen mode, so 2 out of 4 corners will
- // have
- // a radius of 0.
- 0f
- }
- endState.topCornerRadius = endRadius
- endState.bottomCornerRadius = endRadius
+ if (controller.isLaunching) {
+ val endRadius = getWindowRadius(isExpandingFullyAbove)
+ endState.topCornerRadius = endRadius
+ endState.bottomCornerRadius = endRadius
+ }
// We animate the opening window and delegate the view expansion to [this.controller].
val delegate = this.controller
val controller =
object : Controller by delegate {
+ override fun createAnimatorState(): TransitionAnimator.State {
+ if (isLaunching) return delegate.createAnimatorState()
+ val windowRadius = getWindowRadius(isExpandingFullyAbove)
+ return TransitionAnimator.State(
+ top = windowBounds.top,
+ bottom = windowBounds.bottom,
+ left = windowBounds.left,
+ right = windowBounds.right,
+ topCornerRadius = windowRadius,
+ bottomCornerRadius = windowRadius
+ )
+ }
+
override fun onTransitionAnimationStart(isExpandingFullyAbove: Boolean) {
listener?.onTransitionAnimationStart()
@@ -795,6 +819,18 @@
)
}
+ private fun getWindowRadius(isExpandingFullyAbove: Boolean): Float {
+ return if (isExpandingFullyAbove) {
+ // Most of the time, expanding fully above the root view means
+ // expanding in full screen.
+ ScreenDecorationsUtils.getWindowCornerRadius(context)
+ } else {
+ // This usually means we are in split screen mode, so 2 out of 4
+ // corners will have a radius of 0.
+ 0f
+ }
+ }
+
private fun applyStateToWindow(
window: RemoteAnimationTarget,
state: TransitionAnimator.State,
@@ -842,20 +878,41 @@
windowCropF.bottom.roundToInt()
)
+ val windowAnimationDelay =
+ if (controller.isLaunching) {
+ TIMINGS.contentAfterFadeInDelay
+ } else {
+ TIMINGS.contentBeforeFadeOutDelay
+ }
+ val windowAnimationDuration =
+ if (controller.isLaunching) {
+ TIMINGS.contentAfterFadeInDuration
+ } else {
+ TIMINGS.contentBeforeFadeOutDuration
+ }
+ val windowProgress =
+ TransitionAnimator.getProgress(
+ TIMINGS,
+ linearProgress,
+ windowAnimationDelay,
+ windowAnimationDuration
+ )
+
// The alpha of the opening window. If it opens above the expandable, then it should
// fade in progressively. Otherwise, it should be fully opaque and will be progressively
// revealed as the window background color layer above the window fades out.
val alpha =
if (controller.isBelowAnimatingWindow) {
- val windowProgress =
- TransitionAnimator.getProgress(
- TIMINGS,
- linearProgress,
- TIMINGS.contentAfterFadeInDelay,
- TIMINGS.contentAfterFadeInDuration
+ if (controller.isLaunching) {
+ INTERPOLATORS.contentAfterFadeInInterpolator.getInterpolation(
+ windowProgress
)
-
- INTERPOLATORS.contentAfterFadeInInterpolator.getInterpolation(windowProgress)
+ } else {
+ 1 -
+ INTERPOLATORS.contentBeforeFadeOutInterpolator.getInterpolation(
+ windowProgress
+ )
+ }
} else {
1f
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt
index 9bf6b34..679c969 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TransitionAnimator.kt
@@ -59,6 +59,13 @@
1.0f
)
}
+
+ internal fun checkReturnAnimationFrameworkFlag() {
+ check(returnAnimationFrameworkLibrary()) {
+ "isLaunching cannot be false when the returnAnimationFrameworkLibrary flag is " +
+ "disabled"
+ }
+ }
}
private val transitionContainerLocation = IntArray(2)
@@ -558,10 +565,4 @@
}
}
}
-
- private fun checkReturnAnimationFrameworkFlag() {
- check(returnAnimationFrameworkLibrary()) {
- "isLaunching cannot be false when the returnAnimationFrameworkLibrary flag is disabled"
- }
- }
}
diff --git a/packages/SystemUI/checks/Android.bp b/packages/SystemUI/checks/Android.bp
index f65d797..1f502e3 100644
--- a/packages/SystemUI/checks/Android.bp
+++ b/packages/SystemUI/checks/Android.bp
@@ -40,6 +40,7 @@
data: [
":framework",
":androidx.annotation_annotation-nodeps",
+ ":kotlinx-coroutines-core",
],
static_libs: [
"SystemUILintChecker",
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/FlowDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/FlowDetector.kt
new file mode 100644
index 0000000..5868200
--- /dev/null
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/FlowDetector.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2024 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.internal.systemui.lint
+
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.intellij.psi.PsiClassType
+import com.intellij.psi.PsiMethod
+import com.intellij.psi.PsiParameter
+import org.jetbrains.kotlin.psi.psiUtil.isTopLevelKtOrJavaMember
+import org.jetbrains.uast.UCallExpression
+
+/** Detects bad usages of Kotlin Flows */
+class FlowDetector : Detector(), SourceCodeScanner {
+
+ override fun getApplicableMethodNames(): List<String> =
+ listOf(
+ FUN_MUTABLE_SHARED_FLOW,
+ FUN_SHARE_IN,
+ )
+
+ override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) {
+ if (
+ method.name == FUN_MUTABLE_SHARED_FLOW &&
+ method.parent.isTopLevelKtOrJavaMember() &&
+ context.evaluator.getPackage(method)?.qualifiedName == PACKAGE_FLOW
+ ) {
+ context.report(
+ issue = SHARED_FLOW_CREATION,
+ location = context.getNameLocation(node),
+ message =
+ "`MutableSharedFlow()` creates a new shared flow, which has poor performance " +
+ "characteristics"
+ )
+ }
+ if (
+ method.name == FUN_SHARE_IN &&
+ getTypeOfExtensionMethod(method)?.resolve()?.qualifiedName == CLASS_FLOW
+ ) {
+ context.report(
+ issue = SHARED_FLOW_CREATION,
+ location = context.getNameLocation(node),
+ message =
+ "`shareIn()` creates a new shared flow, which has poor performance " +
+ "characteristics"
+ )
+ }
+ }
+
+ companion object {
+ @JvmStatic
+ val SHARED_FLOW_CREATION =
+ Issue.create(
+ id = "SharedFlowCreation",
+ briefDescription = "Shared flow creation",
+ explanation =
+ """
+ Shared flows scale poorly with the number of collectors in use due to
+ their internal buffering mechanism and reliance on thread
+ synchronization. They can also cause memory leaks when used incorrectly.
+ If possible, use `StateFlow` instead.
+ """,
+ moreInfo = "http://go//sysui-shared-flow",
+ category = Category.PERFORMANCE,
+ priority = 8,
+ severity = Severity.ERROR,
+ implementation =
+ Implementation(
+ FlowDetector::class.java,
+ Scope.JAVA_FILE_SCOPE,
+ ),
+ )
+
+ fun getTypeOfExtensionMethod(method: PsiMethod): PsiClassType? {
+ // If this is an extension method whose return type matches receiver
+ val parameterList = method.parameterList
+ if (parameterList.parametersCount > 0) {
+ val firstParameter = parameterList.getParameter(0)
+ if (firstParameter is PsiParameter && firstParameter.name.startsWith("\$this\$")) {
+ return firstParameter.type as? PsiClassType
+ }
+ }
+ return null
+ }
+ }
+}
+
+private const val PACKAGE_FLOW = "kotlinx.coroutines.flow"
+private const val FUN_MUTABLE_SHARED_FLOW = "MutableSharedFlow"
+private const val FUN_SHARE_IN = "shareIn"
+private const val CLASS_FLOW = "$PACKAGE_FLOW.Flow"
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/MissingApacheLicenseDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/MissingApacheLicenseDetector.kt
index 46125be..a162897 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/MissingApacheLicenseDetector.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/MissingApacheLicenseDetector.kt
@@ -25,7 +25,6 @@
import com.android.tools.lint.detector.api.JavaContext
import com.android.tools.lint.detector.api.Location
import com.android.tools.lint.detector.api.Scope
-import com.android.tools.lint.detector.api.Severity
import com.android.tools.lint.detector.api.SourceCodeScanner
import java.time.Year
import org.jetbrains.uast.UComment
@@ -117,8 +116,13 @@
attached at the beginning.""",
category = Category.COMPLIANCE,
priority = 8,
- // ignored by default and then explicitly overridden in SysUI's soong configuration
- severity = Severity.IGNORE,
+ // This check is disabled by default so that it is not accidentally used by internal
+ // modules that have different silencing. This check can be enabled in Soong using
+ // the following configuration:
+ // lint: {
+ // warning_checks: ["MissingApacheLicenseDetector"],
+ // }
+ enabledByDefault = false,
implementation =
Implementation(MissingApacheLicenseDetector::class.java, Scope.JAVA_FILE_SCOPE),
)
diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
index e09aa42..e93264c 100644
--- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
+++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
@@ -33,6 +33,7 @@
BroadcastSentViaContextDetector.ISSUE,
CleanArchitectureDependencyViolationDetector.ISSUE,
DumpableNotRegisteredDetector.ISSUE,
+ FlowDetector.SHARED_FLOW_CREATION,
SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY,
SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY,
NonInjectedMainThreadDetector.ISSUE,
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt
index f3b24a3..edfd59a 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/AndroidStubs.kt
@@ -19,12 +19,16 @@
import com.android.tools.lint.checks.infrastructure.TestFiles.LibraryReferenceTestFile
import java.io.File
+internal val libraryNames =
+ arrayOf(
+ "framework.jar",
+ "androidx.annotation_annotation-nodeps.jar",
+ "kotlinx-coroutines-core.jar",
+ )
+
/*
* This file contains stubs of framework APIs and System UI classes for testing purposes only. The
* stubs are not used in the lint detectors themselves.
*/
internal val androidStubs =
- arrayOf(
- LibraryReferenceTestFile(File("framework.jar").canonicalFile),
- LibraryReferenceTestFile(File("androidx.annotation_annotation-nodeps.jar").canonicalFile),
- )
+ libraryNames.map { LibraryReferenceTestFile(File(it).canonicalFile) }.toTypedArray()
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/FlowDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/FlowDetectorTest.kt
new file mode 100644
index 0000000..4944529
--- /dev/null
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/FlowDetectorTest.kt
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2024 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.internal.systemui.lint
+
+import com.android.tools.lint.checks.infrastructure.TestFiles
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+
+class FlowDetectorTest : SystemUILintDetectorTest() {
+ override fun getDetector(): Detector = FlowDetector()
+
+ override fun getIssues(): List<Issue> = listOf(FlowDetector.SHARED_FLOW_CREATION)
+
+ @Test
+ fun createSharedFlow_viaCallToMutableSharedFlow() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package test.pkg
+
+ import kotlinx.coroutines.flow.MutableSharedFlow
+
+ suspend fun doSomething() {
+ val sharedFlow = MutableSharedFlow<Int>(replay = 2)
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs
+ )
+ .issues(FlowDetector.SHARED_FLOW_CREATION)
+ .run()
+ .expect(
+ """
+src/test/pkg/test.kt:6: Error: MutableSharedFlow() creates a new shared flow, which has poor performance characteristics [SharedFlowCreation]
+ val sharedFlow = MutableSharedFlow<Int>(replay = 2)
+ ~~~~~~~~~~~~~~~~~
+1 errors, 0 warnings
+ """,
+ )
+ }
+
+ @Test
+ fun createSharedFlow_viaCallToShareIn_onFlow() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package test.pkg
+
+ import kotlinx.coroutines.CoroutineScope
+ import kotlinx.coroutines.flow.Flow
+ import kotlinx.coroutines.flow.SharingStarted
+ import kotlinx.coroutines.flow.shareIn
+
+ suspend fun doSomething(scope: CoroutineScope, someFlow: Flow<Int>) {
+ someFlow.shareIn(scope, SharingStarted.Eagerly)
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs
+ )
+ .issues(FlowDetector.SHARED_FLOW_CREATION)
+ .run()
+ .expect(
+ """
+src/test/pkg/test.kt:9: Error: shareIn() creates a new shared flow, which has poor performance characteristics [SharedFlowCreation]
+ someFlow.shareIn(scope, SharingStarted.Eagerly)
+ ~~~~~~~
+1 errors, 0 warnings
+ """,
+ )
+ }
+
+ @Test
+ fun createSharedFlow_viaCallToShareIn_afterOperationChain() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package test.pkg
+
+ import kotlinx.coroutines.CoroutineScope
+ import kotlinx.coroutines.flow.Flow
+ import kotlinx.coroutines.flow.SharingStarted
+ import kotlinx.coroutines.flow.shareIn
+ import kotlinx.coroutines.flow.onStart
+ import kotlinx.coroutines.flow.map
+ import kotlinx.coroutines.flow.distinctUntilChanged
+
+ suspend fun doSomething(scope: CoroutineScope, someFlow: Flow<Int>) {
+ someFlow.onStart { emit(PackageChangeModel.Empty) }
+ .map { reloadComponents(userId, packageManager) }
+ .distinctUntilChanged()
+ .shareIn(scope, SharingStarted.WhileSubscribed(), replay = 1)
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs
+ )
+ .issues(FlowDetector.SHARED_FLOW_CREATION)
+ .run()
+ .expect(
+ """
+src/test/pkg/test.kt:15: Error: shareIn() creates a new shared flow, which has poor performance characteristics [SharedFlowCreation]
+ .shareIn(scope, SharingStarted.WhileSubscribed(), replay = 1)
+ ~~~~~~~
+1 errors, 0 warnings
+ """,
+ )
+ }
+
+ @Test
+ fun createSharedFlow_viaCallToShareIn_onStateFlow() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package test.pkg
+
+ import kotlinx.coroutines.CoroutineScope
+ import kotlinx.coroutines.flow.Flow
+ import kotlinx.coroutines.flow.StateFlow
+ import kotlinx.coroutines.flow.SharingStarted
+ import kotlinx.coroutines.flow.shareIn
+ import kotlinx.coroutines.flow.onStart
+ import kotlinx.coroutines.flow.map
+ import kotlinx.coroutines.flow.distinctUntilChanged
+
+ suspend fun doSomething(someScope: CoroutineScope, someFlow: StateFlow<Int>) {
+ someFlow.onStart { emit(1) }
+ .map { someOtherFunction() }
+ .distinctUntilChanged()
+ .shareIn(someScope, SharingStarted.WhileSubscribed())
+ someFlow.shareIn(someScope, SharingStarted.Eagerly)
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs
+ )
+ .issues(FlowDetector.SHARED_FLOW_CREATION)
+ .run()
+ .expect(
+ """
+src/test/pkg/test.kt:16: Error: shareIn() creates a new shared flow, which has poor performance characteristics [SharedFlowCreation]
+ .shareIn(someScope, SharingStarted.WhileSubscribed())
+ ~~~~~~~
+src/test/pkg/test.kt:17: Error: shareIn() creates a new shared flow, which has poor performance characteristics [SharedFlowCreation]
+ someFlow.shareIn(someScope, SharingStarted.Eagerly)
+ ~~~~~~~
+2 errors, 0 warnings
+ """,
+ )
+ }
+
+ @Test
+ fun createSharedFlow_viaCallToShareIn_onSharedFlow() {
+ lint()
+ .files(
+ TestFiles.kotlin(
+ """
+ package test.pkg
+
+ import kotlinx.coroutines.CoroutineScope
+ import kotlinx.coroutines.flow.Flow
+ import kotlinx.coroutines.flow.SharedFlow
+ import kotlinx.coroutines.flow.SharingStarted
+ import kotlinx.coroutines.flow.shareIn
+ import kotlinx.coroutines.flow.onStart
+ import kotlinx.coroutines.flow.map
+ import kotlinx.coroutines.flow.distinctUntilChanged
+
+ suspend fun doSomething(someScope: CoroutineScope, someFlow: SharedFlow<Int>) {
+ someFlow.onStart { emit(1) }
+ .map { someOtherFunction() }
+ .distinctUntilChanged()
+ .shareIn(someScope, SharingStarted.WhileSubscribed())
+ someFlow.shareIn(someScope, SharingStarted.Eagerly)
+ }
+ """
+ .trimIndent()
+ ),
+ *androidStubs
+ )
+ .issues(FlowDetector.SHARED_FLOW_CREATION)
+ .run()
+ .expect(
+ """
+src/test/pkg/test.kt:16: Error: shareIn() creates a new shared flow, which has poor performance characteristics [SharedFlowCreation]
+ .shareIn(someScope, SharingStarted.WhileSubscribed())
+ ~~~~~~~
+src/test/pkg/test.kt:17: Error: shareIn() creates a new shared flow, which has poor performance characteristics [SharedFlowCreation]
+ someFlow.shareIn(someScope, SharingStarted.Eagerly)
+ ~~~~~~~
+2 errors, 0 warnings
+ """,
+ )
+ }
+}
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/MissingApacheLicenseDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/MissingApacheLicenseDetectorTest.kt
index 78e133f..80d9291 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/MissingApacheLicenseDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/MissingApacheLicenseDetectorTest.kt
@@ -87,6 +87,31 @@
.skipTestModes(TestMode.SUPPRESSIBLE)
.issues(MissingApacheLicenseDetector.ISSUE)
.run()
- .expectContains("License header is missing")
+ .expect(
+ """
+ src/test/pkg/name/MyTest.kt:2: Warning: License header is missing
+ Please add the following copyright and license header to the beginning of the file:
+
+ /*
+ * Copyright (C) ${Year.now().value} 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.
+ */ [MissingApacheLicenseDetector]
+
+ ^
+ 0 errors, 1 warnings
+ """
+ .trimIndent()
+ )
}
}
diff --git a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SystemUILintDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SystemUILintDetectorTest.kt
index 29b3828..b7987f7 100644
--- a/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SystemUILintDetectorTest.kt
+++ b/packages/SystemUI/checks/tests/com/android/internal/systemui/lint/SystemUILintDetectorTest.kt
@@ -14,10 +14,7 @@
abstract class SystemUILintDetectorTest : LintDetectorTest() {
companion object {
- @ClassRule
- @JvmField
- val libraryChecker: LibraryExists =
- LibraryExists("framework.jar", "androidx.annotation_annotation-nodeps.jar")
+ @ClassRule @JvmField val libraryChecker: LibraryExists = LibraryExists(*libraryNames)
}
class LibraryExists(vararg val libraryNames: String) : TestRule {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
index 356bfe2..e07cd05 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt
@@ -79,10 +79,10 @@
) {
val coroutineScope = rememberCoroutineScope()
val currentSceneKey: SceneKey by viewModel.currentScene.collectAsState(CommunalScenes.Blank)
- val touchesAllowed by viewModel.touchesAllowed.collectAsState(initial = false)
val state: MutableSceneTransitionLayoutState = remember {
MutableSceneTransitionLayoutState(
initialScene = currentSceneKey,
+ canChangeScene = { _ -> viewModel.canChangeScene() },
transitions = sceneTransitions,
enableInterruptions = false,
)
@@ -112,14 +112,9 @@
scene(
CommunalScenes.Blank,
userActions =
- if (touchesAllowed) {
- mapOf(
- Swipe(SwipeDirection.Left, fromSource = Edge.Right) to
- CommunalScenes.Communal
- )
- } else {
- emptyMap()
- }
+ mapOf(
+ Swipe(SwipeDirection.Left, fromSource = Edge.Right) to CommunalScenes.Communal
+ )
) {
// This scene shows nothing only allowing for transitions to the communal scene.
Box(modifier = Modifier.fillMaxSize())
@@ -128,13 +123,7 @@
scene(
CommunalScenes.Communal,
userActions =
- if (touchesAllowed) {
- mapOf(
- Swipe(SwipeDirection.Right, fromSource = Edge.Left) to CommunalScenes.Blank
- )
- } else {
- emptyMap()
- },
+ mapOf(Swipe(SwipeDirection.Right, fromSource = Edge.Left) to CommunalScenes.Blank)
) {
CommunalScene(viewModel, colors, dialogFactory, modifier = modifier)
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
index f1f1b57..f539a23 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
@@ -97,6 +97,8 @@
@VisibleForTesting var textAnimatorFactory: (Layout, () -> Unit) -> TextAnimator =
{ layout, invalidateCb ->
TextAnimator(layout, NUM_CLOCK_FONT_ANIMATION_STEPS, invalidateCb) }
+
+ // Used by screenshot tests to provide stability
@VisibleForTesting var isAnimationEnabled: Boolean = true
@VisibleForTesting var timeOverrideInMillis: Long? = null
@@ -242,15 +244,8 @@
}
logger.d({ "onDraw($str1)"}) { str1 = text.toString() }
- // Use textAnimator to render text if animation is enabled.
- // Otherwise default to using standard draw functions.
- if (isAnimationEnabled) {
- // intentionally doesn't call super.onDraw here or else the text will be rendered twice
- textAnimator?.draw(canvas)
- } else {
- super.onDraw(canvas)
- }
-
+ // intentionally doesn't call super.onDraw here or else the text will be rendered twice
+ textAnimator?.draw(canvas)
canvas.restore()
}
@@ -318,7 +313,7 @@
weight = lockScreenWeight,
textSize = -1f,
color = lockScreenColor,
- animate = isAnimationEnabled,
+ animate = true,
duration = APPEAR_ANIM_DURATION,
interpolator = Interpolators.EMPHASIZED_DECELERATE,
delay = 0,
@@ -327,7 +322,7 @@
}
fun animateFoldAppear(animate: Boolean = true) {
- if (isAnimationEnabled && textAnimator == null) {
+ if (textAnimator == null) {
return
}
logger.d("animateFoldAppear")
@@ -344,7 +339,7 @@
weight = dozingWeightInternal,
textSize = -1f,
color = dozingColor,
- animate = animate && isAnimationEnabled,
+ animate = animate,
interpolator = Interpolators.EMPHASIZED_DECELERATE,
duration = ANIMATION_DURATION_FOLD_TO_AOD.toLong(),
delay = 0,
@@ -363,7 +358,7 @@
weight = if (isDozing()) dozingWeight else lockScreenWeight,
textSize = -1f,
color = null,
- animate = isAnimationEnabled,
+ animate = true,
duration = CHARGE_ANIM_DURATION_PHASE_1,
delay = 0,
onAnimationEnd = null
@@ -373,7 +368,7 @@
weight = if (isDozing()) lockScreenWeight else dozingWeight,
textSize = -1f,
color = null,
- animate = isAnimationEnabled,
+ animate = true,
duration = CHARGE_ANIM_DURATION_PHASE_0,
delay = chargeAnimationDelay.toLong(),
onAnimationEnd = startAnimPhase2
@@ -386,7 +381,7 @@
weight = if (isDozing) dozingWeight else lockScreenWeight,
textSize = -1f,
color = if (isDozing) dozingColor else lockScreenColor,
- animate = animate && isAnimationEnabled,
+ animate = animate,
duration = DOZE_ANIM_DURATION,
delay = 0,
onAnimationEnd = null
@@ -445,9 +440,6 @@
onAnimationEnd = onAnimationEnd
)
textAnimator?.glyphFilter = glyphFilter
- if (color != null && !isAnimationEnabled) {
- setTextColor(color)
- }
} else {
// when the text animator is set, update its start values
onTextAnimatorInitialized = Runnable {
@@ -462,9 +454,6 @@
onAnimationEnd = onAnimationEnd
)
textAnimator?.glyphFilter = glyphFilter
- if (color != null && !isAnimationEnabled) {
- setTextColor(color)
- }
}
}
}
@@ -482,7 +471,7 @@
weight = weight,
textSize = textSize,
color = color,
- animate = animate && isAnimationEnabled,
+ animate = animate,
interpolator = null,
duration = duration,
delay = delay,
diff --git a/packages/SystemUI/lint-baseline.xml b/packages/SystemUI/lint-baseline.xml
new file mode 100644
index 0000000..4def93f
--- /dev/null
+++ b/packages/SystemUI/lint-baseline.xml
@@ -0,0 +1,32215 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.4.0-alpha08" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha08">
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mSettingsObserver = new SettingsObserver(context.getMainThreadHandler());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java"
+ line="142"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mContext.getMainExecutor().execute(() -> {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+ line="845"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor());"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java"
+ line="208"
+ column="69"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor());"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java"
+ line="515"
+ column="65"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" return context.getMainExecutor();"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/concurrency/GlobalConcurrencyModule.java"
+ line="94"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mContext.getMainExecutor().execute(() -> {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="1088"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mContext.getMainExecutor().execute(() -> {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="1132"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mContext.getMainExecutor().execute(() -> {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="1191"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mContext.getMainExecutor().execute(() -> {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="1230"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mContext.getMainExecutor().execute(() -> {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="3115"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" context.getMainThreadHandler(), this);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java"
+ line="191"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor());"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java"
+ line="807"
+ column="65"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mContext.getMainExecutor().execute(() ->"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java"
+ line="575"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mContext.getMainExecutor());"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java"
+ line="918"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor());"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+ line="188"
+ column="65"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" new Handler(mContext.getMainLooper())) {"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java"
+ line="63"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor());"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java"
+ line="256"
+ column="69"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mSessionFuture.addListener(this::onStartComplete, mContext.getMainExecutor());"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/ScrollCaptureController.java"
+ line="182"
+ column="76"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" }, mContext.getMainExecutor());"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/ScrollCaptureController.java"
+ line="354"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mUserTracker.addCallback(mUserChangedCallback, mContext.getMainExecutor());"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java"
+ line="230"
+ column="65"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" wifiManager.registerTrafficStateCallback(context.getMainExecutor(),"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java"
+ line="73"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" context.getMainThreadHandler(), this);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java"
+ line="156"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" mContext.getMainThreadHandler()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java"
+ line="159"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="NonInjectedMainThread"
+ message="Replace with injected `@Main Executor`."
+ errorLine1=" context.mainExecutor.execute { unoccludeAnimator?.cancel() }"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerOcclusionManager.kt"
+ line="245"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="MissingSuperCall"
+ message="Overriding method should call `super.onBackPressed`"
+ errorLine1=" override fun onBackPressed() {"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt"
+ line="143"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="MissingSuperCall"
+ message="Overriding method should call `super.onBackPressed`"
+ errorLine1=" override fun onBackPressed() {"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt"
+ line="133"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="MissingSuperCall"
+ message="Overriding method should call `super.onBackPressed`"
+ errorLine1=" override fun onBackPressed() {"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt"
+ line="118"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="MissingSuperCall"
+ message="Overriding method should call `super.onBackPressed`"
+ errorLine1=" override fun onBackPressed() {"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt"
+ line="126"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="MissingSuperCall"
+ message="Overriding method should call `super.onDetachedFromWindow`"
+ errorLine1=" public void onDetachedFromWindow() {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java"
+ line="474"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="MissingSuperCall"
+ message="Overriding method should call `super.onDetachedFromWindow`"
+ errorLine1=" public void onDetachedFromWindow() {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java"
+ line="381"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="MissingSuperCall"
+ message="Overriding method should call `super.onBind`"
+ errorLine1=" override fun onBind(intent: Intent): IBinder? {"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt"
+ line="74"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="WrongViewCast"
+ message="Unexpected implicit cast to `NotificationExpandButton`: layout tag was `ImageView`"
+ errorLine1=" mExpandButton = mView.findViewById(com.android.internal.R.id.expand_button);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java"
+ line="145"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="WrongViewCast"
+ message="Unexpected implicit cast to `NotificationActionListLayout`: layout tag was `LinearLayout`"
+ errorLine1=" mActions = mView.findViewById(com.android.internal.R.id.actions);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java"
+ line="180"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The domain layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.volume.panel.ui.VolumePanelUiEvent"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartable.kt"
+ line="23"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The shared layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.statusbar.pipeline.satellite.ui.DeviceBasedSatelliteBindableIcon"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/icons/shared/BindableIconsRegistry.kt"
+ line="21"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The domain layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.volume.panel.ui.VolumePanelUiEvent"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt"
+ line="23"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the domain layer."
+ errorLine1="import com.android.systemui.media.controls.domain.pipeline.MediaDataManager"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalMediaRepository.kt"
+ line="24"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The ui layer may not depend on the data layer."
+ errorLine1="import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt"
+ line="23"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the domain layer."
+ errorLine1="import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthModule.kt"
+ line="24"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the domain layer."
+ errorLine1="import com.android.systemui.deviceentry.domain.interactor.SystemUIDeviceEntryFaceAuthInteractor"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthModule.kt"
+ line="25"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.deviceentry.ui.binder.LiftToRunFaceAuthBinder"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthModule.kt"
+ line="26"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the domain layer."
+ errorLine1="import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt"
+ line="26"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the domain layer."
+ errorLine1="import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt"
+ line="27"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the domain layer."
+ errorLine1="import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt"
+ line="50"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the domain layer."
+ errorLine1="import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt"
+ line="51"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the domain layer."
+ errorLine1="import com.android.systemui.power.domain.interactor.PowerInteractor"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryFaceAuthRepository.kt"
+ line="59"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The ui layer may not depend on the data layer."
+ errorLine1="import com.android.systemui.qs.footer.data.model.UserSwitcherStatusModel"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt"
+ line="34"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.controls.ui.ControlsActivity"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt"
+ line="34"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.controls.ui.ControlsUiController"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt"
+ line="35"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the domain layer."
+ errorLine1="import com.android.systemui.keyguard.domain.interactor.InWindowLauncherUnlockAnimationInteractor"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/InWindowLauncherUnlockAnimationRepository.kt"
+ line="20"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The domain layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/internet/domain/interactor/InternetTileDataInteractor.kt"
+ line="40"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The ui layer may not depend on the data layer."
+ errorLine1="import com.android.systemui.keyguard.data.repository.KeyguardBlueprintRepository"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/KeyguardBlueprintCommandListener.kt"
+ line="20"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The domain layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt"
+ line="30"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The domain layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt"
+ line="31"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The domain layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt"
+ line="32"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The domain layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Type"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt"
+ line="33"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.keyguard.ui.view.layout.blueprints.DefaultKeyguardBlueprint.Companion.DEFAULT"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt"
+ line="25"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.keyguard.ui.view.layout.blueprints.KeyguardBlueprintModule"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt"
+ line="26"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt"
+ line="27"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the domain layer."
+ errorLine1="import com.android.systemui.bouncer.domain.interactor.BouncerMessageAuditLogger"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt"
+ line="24"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The data layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.keyguard.ui.binder.SideFpsProgressBarViewBinder"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt"
+ line="25"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The domain layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.statusbar.notification.stack.ui.viewmodel.SharedNotificationContainerViewModel"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt"
+ line="26"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The domain layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.media.controls.ui.view.MediaViewHolder"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt"
+ line="81"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The ui layer may not depend on the data layer."
+ errorLine1="import com.android.systemui.user.data.source.UserRecord"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/legacyhelper/ui/LegacyUserUiHelper.kt"
+ line="24"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The domain layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.media.controls.ui.view.MediaViewHolder"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt"
+ line="84"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The domain layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.statusbar.pipeline.satellite.ui.model.SatelliteIconModel"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconInteractor.kt"
+ line="36"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The ui layer may not depend on the data layer."
+ errorLine1="import com.android.systemui.people.data.model.PeopleTileModel"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/ui/viewmodel/PeopleViewModel.kt"
+ line="29"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The ui layer may not depend on the data layer."
+ errorLine1="import com.android.systemui.people.data.repository.PeopleTileRepository"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/ui/viewmodel/PeopleViewModel.kt"
+ line="30"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The ui layer may not depend on the data layer."
+ errorLine1="import com.android.systemui.people.data.repository.PeopleWidgetRepository"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/ui/viewmodel/PeopleViewModel.kt"
+ line="31"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The domain layer may not depend on the ui layer."
+ errorLine1="import com.android.systemui.bouncer.ui.BouncerView"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt"
+ line="38"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The shared layer may not depend on the data layer."
+ errorLine1="import com.android.systemui.qs.pipeline.data.model.RestoreData"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt"
+ line="24"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The shared layer may not depend on the data layer."
+ errorLine1="import com.android.systemui.qs.pipeline.data.repository.UserTileSpecRepository"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt"
+ line="25"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The ui layer may not depend on the data layer."
+ errorLine1="import com.android.systemui.keyboard.data.repository.KeyboardRepository"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/viewmodel/StickyKeysIndicatorViewModel.kt"
+ line="20"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The ui layer may not depend on the data layer."
+ errorLine1="import com.android.systemui.keyboard.stickykeys.data.repository.StickyKeysRepository"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyboard/stickykeys/ui/viewmodel/StickyKeysIndicatorViewModel.kt"
+ line="21"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="CleanArchitectureDependencyViolation"
+ message="The shared layer may not depend on the data layer."
+ errorLine1="import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository"
+ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiNetworkModel.kt"
+ line="25"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="class ActionReceiver("
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/ActionReceiver.kt"
+ line="50"
+ column="7"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="public class GroupCoalescer implements Dumpable, PipelineDumpable {"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java"
+ line="70"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="public class KeyguardIndicationRotateTextViewController extends"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardIndicationRotateTextViewController.java"
+ line="62"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="public class LightBarTransitionsController implements Dumpable {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java"
+ line="48"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="public class LockIconView extends FrameLayout implements Dumpable {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/LockIconView.java"
+ line="47"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="public class NotificationBackgroundView extends View implements Dumpable {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java"
+ line="47"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="public class NotificationStackScrollLayout"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java"
+ line="151"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="class PendingRemovalStore @Inject constructor("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/PendingRemovalStore.kt"
+ line="19"
+ column="7"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="public class QSContainerImpl extends FrameLayout implements Dumpable {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java"
+ line="47"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="class QSTileViewModelAdapter"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/viewmodel/QSTileViewModelAdapter.kt"
+ line="47"
+ column="7"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="class QSTileViewModelImpl<DATA_TYPE>("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt"
+ line="72"
+ column="7"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="class RoundedCornerResDelegateImpl("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt"
+ line="48"
+ column="7"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="class StatusBarModePerDisplayRepositoryImpl"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModePerDisplayRepository.kt"
+ line="108"
+ column="7"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="public final class StatusBarTouchableRegionManager implements Dumpable {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java"
+ line="61"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="public class SwipeHelper implements Gefingerpoken, Dumpable {"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/SwipeHelper.java"
+ line="64"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="public class SysUiState implements Dumpable {"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/model/SysUiState.java"
+ line="38"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="class TableLogBuffer("
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt"
+ line="78"
+ column="7"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="open class UserBroadcastDispatcher("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt"
+ line="48"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="DumpableNotRegistered"
+ message="Any class implementing `Dumpable` must call `DumpManager.registerNormalDumpable` or `DumpManager.registerCriticalDumpable`"
+ errorLine1="public class ViewState implements Dumpable {"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java"
+ line="47"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="MissingClass"
+ message="Class referenced in the layout file, `com.android.systemui.multishade.ui.view.MultiShadeView`, was not found in the project or the libraries"
+ errorLine1="<com.android.systemui.multishade.ui.view.MultiShadeView"
+ errorLine2="^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/multi_shade.xml"
+ line="19"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="MissingClass"
+ message="Class referenced in the layout file, `com.android.systemui.biometrics.UdfpsEnrollView`, was not found in the project or the libraries"
+ errorLine1="<com.android.systemui.biometrics.UdfpsEnrollView"
+ errorLine2="^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/udfps_enroll_view.xml"
+ line="17"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java"
+ line="47"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java"
+ line="166"
+ column="43"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWm = mContext.getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistDisclosure.java"
+ line="52"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java"
+ line="409"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mContext.getSystemService(StatusBarManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java"
+ line="459"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mContext.getSystemService(StatusBarManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java"
+ line="475"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" final StatusBarManager statusBarManager = mContext.getSystemService(StatusBarManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java"
+ line="485"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWindowManager = mContext.getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java"
+ line="343"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+ line="808"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mAccessibilityManager = context.getSystemService(AccessibilityManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java"
+ line="68"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" val jobScheduler = context.getSystemService(JobScheduler::class.java)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt"
+ line="183"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWindowManager = context.getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/BiometricPromptLayout.java"
+ line="67"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" val accessibilityManager = view.context.getSystemService(AccessibilityManager::class.java)!!"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt"
+ line="91"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" val windowManager = requireNotNull(view.context.getSystemService(WindowManager::class.java))"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt"
+ line="76"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" requireNotNull(view.context.getSystemService(AccessibilityManager::class.java))"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewSizeBinder.kt"
+ line="78"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+ line="114"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" return applicationContext.getSystemService(Context.EUICC_SERVICE) as EuiccManager?"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorModule.kt"
+ line="54"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt"
+ line="167"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mMediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java"
+ line="74"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" context.getSystemService(Context.MEDIA_PROJECTION_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java"
+ line="77"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mUiModeManager = mContext.getSystemService(UiModeManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+ line="856"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+ line="864"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService("
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+ line="875"
+ column="63"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+ line="879"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+ line="885"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mContext.getSystemService(Context.NOTIFICATION_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+ line="2913"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" it.context.getSystemService(InputMethodManager::class.java)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt"
+ line="80"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" InputManager inputManager = mContext.getSystemService(InputManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java"
+ line="520"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWindowManager = mContext.getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayWindow.java"
+ line="66"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mClipboardManager = context.getSystemService(ClipboardManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/ClipboardView.java"
+ line="37"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" val am = context.getSystemService(ActivityManager::class.java)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestReceiver.kt"
+ line="48"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" context.getSystemService(AccessibilityManager::class.java)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt"
+ line="26"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" val imeManager = view.context.getSystemService(InputMethodManager::class.java)!!"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialPasswordViewBinder.kt"
+ line="36"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" .getSystemService(android.telecom.TelecomManager::class.java)!!"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/CredentialViewModel.kt"
+ line="154"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" .getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/display/DisplayHelper.java"
+ line="50"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" final PowerManager pm = getSystemService(PowerManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/doze/DozeService.java"
+ line="119"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" context.getSystemService(Context.WINDOW_SERVICE) as WindowManager"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/DragToInteractView.kt"
+ line="90"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" return mContext.getSystemService(InputManager.class)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java"
+ line="1205"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mClipboardManager = requireNonNull(getSystemService(ClipboardManager.class));"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java"
+ line="61"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" InputMethodManager imm = getSystemService(InputMethodManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/clipboardoverlay/EditTextActivity.java"
+ line="133"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" (AccessibilityManager) getContext().getSystemService("
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java"
+ line="2504"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mTetheringManager = context.getSystemService(TetheringManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java"
+ line="105"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java"
+ line="106"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="77"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWallpaperManager = getDisplayContext().getSystemService(WallpaperManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java"
+ line="181"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" getDisplayContext().getSystemService(DisplayManager.class)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java"
+ line="188"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" DisplayManager displayManager = context.getSystemService(DisplayManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java"
+ line="198"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" .getSystemService(WindowManager.class)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java"
+ line="518"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWindowManager = mWindowContext.getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java"
+ line="508"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWindowManager = mContext.getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/InattentiveSleepWarningView.java"
+ line="46"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" NotificationManager noMan = mContext.getSystemService(NotificationManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java"
+ line="109"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" NotificationManager noMan = mContext.getSystemService(NotificationManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java"
+ line="148"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" context.getSystemService(TelephonyManager.class).createForSubscriptionId("
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java"
+ line="963"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonView.java"
+ line="177"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" this.mWindowManager = mContext.getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java"
+ line="154"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java"
+ line="858"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" this.mWindowManager = mContext.getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java"
+ line="141"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" final InputManager inputManager = mContext.getSystemService(InputManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java"
+ line="353"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" LayoutInflater inflater = (LayoutInflater) mContext.getSystemService("
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java"
+ line="601"
+ column="61"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" InputManager im = context.getSystemService(InputManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java"
+ line="206"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" uiBgExecutor.execute(() -> mMediaRouter = mContext.getSystemService(MediaRouter.class));"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java"
+ line="109"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mDisplayService = mContext.getSystemService(DisplayManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java"
+ line="110"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mEuiccManager = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java"
+ line="87"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java"
+ line="105"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" message = mContext.getSystemService(DevicePolicyManager.class).getResources()"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java"
+ line="765"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" message = mContext.getSystemService(DevicePolicyManager.class).getResources()"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java"
+ line="788"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="1528"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mContext.getSystemService(PowerManager.class).wakeUp(mSystemClock.uptimeMillis(),"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="1715"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" final UserManager um = (UserManager) mContext.getSystemService("
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="2684"
+ column="63"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="2736"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mContext.getSystemService(Context.STATUS_BAR_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="3413"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" getApplicationContext().getSystemService(LauncherApps.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java"
+ line="163"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" NotificationManager notiMan = mContext.getSystemService(NotificationManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java"
+ line="96"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" WindowManager windowManager = mContext.getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/LegacyLockIconViewController.java"
+ line="435"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" context.getSystemService(Context.STATUS_BAR_SERVICE) as StatusBarManager"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt"
+ line="237"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java"
+ line="192"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java"
+ line="206"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" windowContext.getSystemService(AccessibilityManager.class),"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java"
+ line="163"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" windowContext.getSystemService(WindowManager.class),"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java"
+ line="164"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/Magnification.java"
+ line="215"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java"
+ line="111"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWindowManager = mContext.getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java"
+ line="112"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" .getSystemService(android.app.Service.STATUS_BAR_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java"
+ line="81"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" context.getSystemService(Context.STATUS_BAR_SERVICE) as StatusBarManager"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt"
+ line="201"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" val audioManager: AudioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManager.kt"
+ line="46"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" final UserManager um = mContext.getSystemService(UserManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java"
+ line="881"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" val statusBarManager = context.getSystemService(Context.STATUS_BAR_SERVICE)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt"
+ line="68"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" val statusBarManager = context.getSystemService(Context.STATUS_BAR_SERVICE)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt"
+ line="159"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mNotificationManager = context.getSystemService(NotificationManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java"
+ line="253"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mStatusBarManager = context.getSystemService(StatusBarManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java"
+ line="254"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/MirrorWindowControl.java"
+ line="77"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mDisplayManager = mContext.getSystemService(DisplayManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarControllerImpl.java"
+ line="142"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" return context.getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarModule.java"
+ line="72"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" WindowManager wm = getContext().getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java"
+ line="729"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" WindowManager wm = getContext().getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java"
+ line="830"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mManager = getHost().getUserContext().getSystemService(ColorDisplayManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java"
+ line="136"
+ column="47"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" final NotificationManager nm = context.getSystemService(NotificationManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java"
+ line="57"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mContext.getSystemService(NotificationManager.class).deleteNotificationChannel(GENERAL);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java"
+ line="144"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" (AudioManager) mCmd.context.getSystemService(Context.AUDIO_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java"
+ line="93"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java"
+ line="508"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java"
+ line="285"
+ column="47"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mKeyguardManager = context.getSystemService(KeyguardManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java"
+ line="286"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" LayoutInflater inflater = (LayoutInflater) getContext().getSystemService("
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java"
+ line="316"
+ column="65"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/NumPadKey.java"
+ line="109"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" LayoutInflater inflater = (LayoutInflater) getContext().getSystemService("
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/NumPadKey.java"
+ line="110"
+ column="65"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mContext.getSystemService(InputMethodManager.class)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java"
+ line="284"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java"
+ line="145"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" JobScheduler jobScheduler = context.getSystemService(JobScheduler.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleBackupFollowUpJob.java"
+ line="74"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mJobScheduler = mContext.getSystemService(JobScheduler.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleBackupFollowUpJob.java"
+ line="92"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mPeopleManager = context.getSystemService(PeopleManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java"
+ line="204"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" JobScheduler jobScheduler = mContext.getSystemService(JobScheduler.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java"
+ line="1134"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" KeyguardManager keyguardManager = mContext.getSystemService(KeyguardManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java"
+ line="190"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mNoMan = mContext.getSystemService(NotificationManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+ line="200"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mPowerMan = (PowerManager) context.getSystemService(Context.POWER_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+ line="201"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mKeyguard = mContext.getSystemService(KeyguardManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+ line="202"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mPowerManager = context.getSystemService(PowerManager::class.java)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt"
+ line="125"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mUserTracker.getUserContext().getSystemService(ClipboardManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java"
+ line="77"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" WindowManager wm = this.mPanelView.getContext().getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java"
+ line="527"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mInputMethodManager = targetContext.getSystemService(InputMethodManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java"
+ line="1111"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWindowManager = mContext.getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java"
+ line="484"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java"
+ line="144"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java"
+ line="113"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mContext.getSystemService(Context.WINDOW_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java"
+ line="115"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" NotificationManager notificationManager = context.getSystemService("
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotServiceErrorReceiver.java"
+ line="36"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" DevicePolicyManager devicePolicyManager = context.getSystemService("
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotServiceErrorReceiver.java"
+ line="38"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" final WindowManager wm = mContext.getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java"
+ line="311"
+ column="47"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" context.getSystemService(Context.DEVICE_POLICY_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java"
+ line="140"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" context.getSystemService(Context.CONNECTIVITY_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java"
+ line="142"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mVpnManager = context.getSystemService(VpnManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java"
+ line="143"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java"
+ line="145"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" LauncherApps apps = getContext().getSystemService(LauncherApps.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/ShortcutPicker.java"
+ line="61"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" getSystemService(SliceManager.class).grantPermissionFromUser(mUri, mCallingPkg,"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/SlicePermissionActivity.java"
+ line="108"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mKeyguardManager = context.getSystemService(KeyguardManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java"
+ line="159"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mKeyguardManager = context.getSystemService(KeyguardManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java"
+ line="110"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mA11yManager = (AccessibilityManager) mContext.getSystemService("
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java"
+ line="215"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mContext.getSystemService(InputManager.class)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java"
+ line="479"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mContext.getSystemService(PowerManager.class).goToSleep(SystemClock.uptimeMillis(),"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java"
+ line="509"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" context.getSystemService(WallpaperManager.class),"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java"
+ line="62"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mDisplayManager = mContext.getSystemService(DisplayManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java"
+ line="176"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" return usercontext.getSystemService(UserManager.class).isPrivateProfile();"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java"
+ line="591"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/TimeoutHandler.java"
+ line="96"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java"
+ line="104"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" DisplayManager mDisplayManager = mContext.getSystemService(DisplayManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/toast/ToastUI.java"
+ line="122"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" view.getContext().getSystemService(WindowManager.class)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java"
+ line="48"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWindowManager = mView.getContext().getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDialogMeasureAdapter.java"
+ line="57"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mUiModeManager = host.getUserContext().getSystemService(UiModeManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java"
+ line="88"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mUsbPort = port.getUsbPort(getSystemService(UsbManager.class));"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbContaminantActivity.java"
+ line="60"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" LayoutInflater inflater = getSystemService(LayoutInflater.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbDialogActivity.java"
+ line="102"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" return requireNotNull(context.getSystemService(serviceType))"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/utils/UserScopedService.kt"
+ line="64"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mCaptioningManager.set(userContext.getSystemService(CaptioningManager.class));"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java"
+ line="343"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java"
+ line="342"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java"
+ line="343"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" return context.getSystemService(PowerManager.class)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java"
+ line="93"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWm = context.getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+ line="279"
+ column="23"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" .getSystemService(AccessibilityManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+ line="776"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java"
+ line="140"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWindowManager = mContext.getSystemService(WindowManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java"
+ line="141"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mWM = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingAnimation.java"
+ line="203"
+ column="47"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java"
+ line="114"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mNoMan = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+ line="140"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+ line="155"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="NonInjectedService"
+ message="Use `@Inject` to get system-level service handles instead of `Context.getSystemService()`"
+ errorLine1=" mUserManager = context.getSystemService(UserManager.class);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+ line="158"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" = Settings.Global.getUriFor(Settings.Global.ALWAYS_ON_DISPLAY_CONSTANTS);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java"
+ line="148"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" final String value = Settings.Global.getString(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/doze/AlwaysOnDisplayPolicy.java"
+ line="169"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/animation/data/repository/AnimationStatusRepository.kt"
+ line="62"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SystemSettings instead"
+ errorLine1=" Settings.System.getUriFor(SHOW_BATTERY_PERCENT),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java"
+ line="215"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Settings.Global.getUriFor(Settings.Global.BATTERY_ESTIMATES_LAST_UPDATE_TIME),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterViewController.java"
+ line="223"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SystemSettings instead"
+ errorLine1=" mHasPercentage = Settings.System.getInt(getContext().getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java"
+ line="53"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SystemSettings instead"
+ errorLine1=" Settings.System.putInt(getContext().getContentResolver(), SHOW_BATTERY_PERCENT, v ? 1 : 0);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java"
+ line="89"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SystemSettings instead"
+ errorLine1=" Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS_MODE);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java"
+ line="73"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" return Settings.Secure.getInt(context.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java"
+ line="668"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.putInt(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+ line="2917"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" return Settings.Secure.getInt(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java"
+ line="152"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" boolean showOnboarding = Settings.Secure.getInt(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java"
+ line="167"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" && Settings.Secure.getInt(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java"
+ line="169"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.putInt(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java"
+ line="173"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.getUriFor(Settings.Secure.DOZE_QUICK_PICKUP_GESTURE);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java"
+ line="475"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.getUriFor(Settings.Secure.DOZE_PICK_UP_GESTURE);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java"
+ line="477"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.getUriFor(Settings.Secure.DOZE_ALWAYS_ON);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java"
+ line="479"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.getUriFor(Settings.Secure.NOTIFICATION_BUBBLES);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java"
+ line="80"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true,"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java"
+ line="424"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SystemSettings instead"
+ errorLine1=" Settings.System.getString("
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java"
+ line="2328"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SystemSettings instead"
+ errorLine1=" Settings.System.getUriFor(Settings.System.TIME_12_24),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java"
+ line="2462"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" return Settings.Global.getInt(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java"
+ line="3051"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java"
+ line="3069"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" String soundPath = Settings.Global.getString(cr, Settings.Global.LOCK_SOUND);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="1564"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" soundPath = Settings.Global.getString(cr, Settings.Global.UNLOCK_SOUND);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="1571"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" soundPath = Settings.Global.getString(cr, Settings.Global.TRUSTED_SOUND);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="1578"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.getInt("
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt"
+ line="157"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.getString(getContext().getContentResolver(),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java"
+ line="254"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+ line="559"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" mContext.getContentResolver().registerContentObserver(Global.getUriFor(Global.MOBILE_DATA),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java"
+ line="200"
+ column="70"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" mContext.getContentResolver().registerContentObserver(Global.getUriFor("
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java"
+ line="202"
+ column="70"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SystemSettings instead"
+ errorLine1=" Settings.System.getUriFor(Settings.System.TOUCHPAD_NATURAL_SCROLLING), false,"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/NaturalScrollingSettingObserver.kt"
+ line="55"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.getUriFor(Settings.Secure.ASSISTANT),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java"
+ line="245"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.getUriFor(Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java"
+ line="248"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.getUriFor(Secure.SEARCH_ALL_ENTRYPOINTS_ENABLED),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java"
+ line="251"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java"
+ line="254"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.putString(mCurrentUserContext.getContentResolver(),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java"
+ line="139"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" boolean airplaneMode = (Settings.Global.getInt(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+ line="1048"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" if ("1".equals(Settings.Global.getString(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java"
+ line="117"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" final String soundPath = Settings.Global.getString(context.getContentResolver(),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java"
+ line="61"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.getUriFor(LOCK_SCREEN_SHOW_NOTIFICATIONS);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java"
+ line="108"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.getUriFor(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java"
+ line="110"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" final int showDismissSetting = Settings.Global.getInt(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java"
+ line="298"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Settings.Global.getUriFor(Settings.Global.USER_SWITCHER_ENABLED),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java"
+ line="3664"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" final String config = Settings.Global.getString(getContext().getContentResolver(),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationSnooze.java"
+ line="270"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" final int mode = Settings.Global.getInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE,"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+ line="352"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" && Settings.Global.getInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0) > 0;"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+ line="358"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Settings.Global.putInt("
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+ line="674"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Settings.Global.putInt("
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+ line="678"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" resolver.registerContentObserver(Settings.Global.getUriFor("
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+ line="183"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Settings.Global.getUriFor(Settings.Global.SHOW_TEMPERATURE_WARNING),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+ line="198"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Settings.Global.getUriFor(Settings.Global.SHOW_USB_TEMPERATURE_ALARM),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+ line="209"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" mEnableSkinTemperatureWarning = Settings.Global.getInt(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+ line="556"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" mEnableUsbTemperatureAlarm = Settings.Global.getInt(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+ line="591"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" bootCount = Settings.Global.getInt(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+ line="625"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" pw.println(Settings.Global.getInt(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+ line="679"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Settings.Global.getUriFor(Settings.Global.DEVELOPMENT_SETTINGS_ENABLED), false,"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSFooterView.java"
+ line="179"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" return (Settings.Global.getInt(cr, Settings.Global.DEVICE_PROVISIONED, 0) != 0) &&"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/Recents.java"
+ line="131"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" (Settings.Secure.getInt(cr, Settings.Secure.USER_SETUP_COMPLETE, 0) != 0);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/Recents.java"
+ line="132"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SystemSettings instead"
+ errorLine1=" mOriginalShowTaps = Settings.System.getInt("
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java"
+ line="163"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SystemSettings instead"
+ errorLine1=" Settings.System.putInt(getContentResolver(), Settings.System.SHOW_TOUCHES, value);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java"
+ line="472"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" return Settings.Secure.getInt(mContext.createContextAsUser(owner, 0)"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java"
+ line="959"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" float maxPages = Settings.Secure.getFloat(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/ScrollCaptureController.java"
+ line="179"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.getUriFor(mKey), /* notifyForDescendants= */"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java"
+ line="84"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" return Settings.Secure.getUriFor(name);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java"
+ line="51"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" return Settings.Secure.putString(mContentResolver, name, value, overrideableByRestore);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java"
+ line="62"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" return Settings.Secure.putString(mContentResolver, name, value, tag, makeDefault);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/settings/SecureSettingsImpl.java"
+ line="81"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SystemSettings instead"
+ errorLine1=" return Settings.System.getUriFor(name);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/settings/SystemSettingsImpl.java"
+ line="51"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SystemSettings instead"
+ errorLine1=" return Settings.System.putString(mContentResolver, name, value, overrideableByRestore);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/settings/SystemSettingsImpl.java"
+ line="62"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SystemSettings instead"
+ errorLine1=" mLessRows = ((Settings.System.getInt(context.getContentResolver(), "qs_less_rows", 0) != 0)"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java"
+ line="66"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" String current = Settings.Secure.getString(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java"
+ line="100"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" if (Settings.Secure.getInt(getContext().getContentResolver(), SETTING_SEEN_TUNER_WARNING,"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java"
+ line="105"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.putInt(getContext().getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java"
+ line="163"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Uri uri = Settings.Secure.getUriFor(key);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java"
+ line="217"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Secure.putInt(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java"
+ line="321"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.putString(getContext().getContentResolver(), key, value ? "1" : "0");"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java"
+ line="57"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" return Settings.Global.getInt("
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt"
+ line="194"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE),"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt"
+ line="166"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Settings.Global.getString("
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt"
+ line="363"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" final int settingsFlag = Settings.Global.getInt(context.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/Utils.java"
+ line="102"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" int flag = Settings.Secure.getInt(context.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/Utils.java"
+ line="116"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" final int zen = Settings.Global.getInt(mContext.getContentResolver(),"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java"
+ line="655"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Settings.Global.getUriFor(Settings.Global.ZEN_MODE);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java"
+ line="1157"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Settings.Global.getUriFor(Settings.Global.ZEN_MODE_CONFIG_ETAG);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java"
+ line="1159"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" int ringerCount = Settings.Secure.getInt(cr, Settings.Secure.MANUAL_RINGER_TOGGLE_COUNT, 0);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java"
+ line="1397"
+ column="43"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Settings.Secure.putInt(cr, Settings.Secure.MANUAL_RINGER_TOGGLE_COUNT, ringerCount + 1);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java"
+ line="1398"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" return Global.getInt(mResolver, Global.DEVICE_PROVISIONED, 0) != 0;"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+ line="372"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" Global.getUriFor(Global.DEVICE_PROVISIONED), false, this);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+ line="380"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" Secure.getUriFor(Secure.USER_SETUP_COMPLETE), false, this, mUserId);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+ line="382"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a GlobalSettings instead"
+ errorLine1=" if (Global.getUriFor(Global.DEVICE_PROVISIONED).equals(uri)"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+ line="389"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="StaticSettingsProvider"
+ message="`@Inject` a SecureSettings instead"
+ errorLine1=" || Secure.getUriFor(Secure.USER_SETUP_COMPLETE).equals(uri)) {"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java"
+ line="390"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="CanvasSize"
+ message="Calling `Canvas.getHeight()` is usually wrong; you should be calling `getHeight()` instead"
+ errorLine1=" canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), pt);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java"
+ line="155"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="CanvasSize"
+ message="Calling `Canvas.getWidth()` is usually wrong; you should be calling `getWidth()` instead"
+ errorLine1=" canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), pt);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java"
+ line="155"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="CustomViewStyleable"
+ message="By convention, the custom view (`KeyguardAffordanceView`) and the declare-styleable (`ImageView`) should have the same name (various editor features rely on this convention)"
+ errorLine1=" TypedArray a = context.obtainStyledAttributes(attrs, android.R.styleable.ImageView);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java"
+ line="130"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="CustomViewStyleable"
+ message="By convention, the custom view (`PasswordTextView`) and the declare-styleable (`View`) should have the same name (various editor features rely on this convention)"
+ errorLine1=" TypedArray a = context.obtainStyledAttributes(attrs, android.R.styleable.View);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java"
+ line="107"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="CustomViewStyleable"
+ message="By convention, the custom view (`ResizingSpace`) and the declare-styleable (`ViewGroup_Layout`) should have the same name (various editor features rely on this convention)"
+ errorLine1=" TypedArray a = context.obtainStyledAttributes(attrs, android.R.styleable.ViewGroup_Layout);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/ResizingSpace.java"
+ line="35"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="CustomViewStyleable"
+ message="By convention, the custom view (`SeekBarWithIconButtonsView`) and the declare-styleable (`SeekBarWithIconButtonsView_Layout`) should have the same name (various editor features rely on this convention)"
+ errorLine1=" R.styleable.SeekBarWithIconButtonsView_Layout,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java"
+ line="87"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="CutPasteId"
+ message="The id `R.id.app_or_structure_spinner` has already been looked up in this method; possible cut & paste error?"
+ errorLine1=" val anchor = parent.requireViewById<View>(R.id.app_or_structure_spinner)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt"
+ line="611"
+ column="22"/>
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt"
+ line="601"
+ column="23"
+ message="First usage here"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+ errorLine1=" String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+ line="1839"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+ errorLine1=" demoTime = String.format("%02d00", majorVersion % 24);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+ line="167"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+ errorLine1=" mPredictionLog.log(String.format("Prediction [%d,%d,%d,%d,%f,%d]","
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java"
+ line="914"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+ errorLine1=" (isWithinInsets ? mGestureLogInsideInsets : mGestureLogOutsideInsets).log(String.format("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java"
+ line="1034"
+ column="87"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `toLowerCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`."
+ errorLine1=" cmd = args.get(1).toLowerCase();"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/flags/FlagCommand.java"
+ line="75"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+ errorLine1=" return String.format("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java"
+ line="65"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+ errorLine1=" return String.format("{\"type\":\"tag\", \"time\":%d, \"tag\":\"%s\", \"info\":\"%s\"}","
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java"
+ line="85"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+ errorLine1=" return String.format(FILENAME_PATTERN, time, fileExtension(format));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java"
+ line="483"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+ errorLine1=" return String.format(CONNECTED_DISPLAY_FILENAME_PATTERN, time, displayId,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java"
+ line="485"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `toLowerCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`."
+ errorLine1=" info.setContentDescription(mContentDescription.toLowerCase());"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java"
+ line="798"
+ column="64"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+ errorLine1=" .setContentText(String.format("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java"
+ line="107"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+ errorLine1=" pw.println(String.format(" mCurrentView: id=%s (%dx%d) %s %f","
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java"
+ line="1128"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+ errorLine1=" pw.println(String.format(" disabled=0x%08x vertical=%s darkIntensity=%.2f","
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java"
+ line="1134"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `toLowerCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`."
+ errorLine1=" b.append(s.substring(1).toLowerCase());"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java"
+ line="139"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+ errorLine1=" state.secondaryLabel = String.format("%d...", countdown);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java"
+ line="151"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+ errorLine1=" secondaryLabel = String.format("%d...", countDown)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/screenrecord/domain/ui/ScreenRecordTileMapper.kt"
+ line="64"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `toLowerCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`."
+ errorLine1=" String colorString = systemPalette.getPackageName().toLowerCase();"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java"
+ line="728"
+ column="70"/>
+ </issue>
+
+ <issue
+ id="DuplicateDefinition"
+ message="`android:textSize` has already been defined in this `<style>`"
+ errorLine1=" <item name="android:textSize">@dimen/notification_importance_channel_text</item>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/styles.xml"
+ line="683"
+ column="15"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/styles.xml"
+ line="680"
+ column="9"
+ message="Previously defined here"/>
+ </issue>
+
+ <issue
+ id="DuplicateDefinition"
+ message="`android:textSize` has already been defined in this `<style>`"
+ errorLine1=" <item name="android:textSize">@dimen/notification_importance_channel_group_text</item>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/styles.xml"
+ line="690"
+ column="15"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/styles.xml"
+ line="687"
+ column="9"
+ message="Previously defined here"/>
+ </issue>
+
+ <issue
+ id="DuplicateDefinition"
+ message="`android:textSize` has already been defined in this `<style>`"
+ errorLine1=" <item name="android:textSize">@dimen/notification_importance_channel_group_text</item>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/styles.xml"
+ line="697"
+ column="15"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/styles.xml"
+ line="694"
+ column="9"
+ message="Previously defined here"/>
+ </issue>
+
+ <issue
+ id="DuplicateIncludedIds"
+ message="Duplicate id @+id/wifi_combo, defined or included multiple times in layout/new_status_bar_wifi_group.xml: [layout/new_status_bar_wifi_group.xml defines @+id/wifi_combo, layout/new_status_bar_wifi_group.xml => layout/status_bar_wifi_group_inner.xml defines @+id/wifi_combo]"
+ errorLine1=" <include layout="@layout/status_bar_wifi_group_inner" />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/new_status_bar_wifi_group.xml"
+ line="26"
+ column="5"
+ message="Duplicate id @+id/wifi_combo, defined or included multiple times in layout/new_status_bar_wifi_group.xml: [layout/new_status_bar_wifi_group.xml defines @+id/wifi_combo, layout/new_status_bar_wifi_group.xml => layout/status_bar_wifi_group_inner.xml defines @+id/wifi_combo]"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/new_status_bar_wifi_group.xml"
+ line="21"
+ column="5"
+ message="Defined here"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/status_bar_wifi_group_inner.xml"
+ line="52"
+ column="13"
+ message="Defined here, included via layout/new_status_bar_wifi_group.xml => layout/status_bar_wifi_group_inner.xml defines @+id/wifi_combo"/>
+ </issue>
+
+ <issue
+ id="ExactAlarm"
+ message="`USE_EXACT_ALARM` can only be used when targeting API level 33 or higher"
+ errorLine1=" <uses-permission android:name="android.permission.USE_EXACT_ALARM"/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+ line="175"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="InconsistentLayout"
+ message="The id "midGuideline" in layout "biometric_prompt_constraint_layout" is missing from the following layout configurations: layout, layout-sw600dp (present in layout-land)"
+ errorLine1=" android:id="@+id/midGuideline""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout-land/biometric_prompt_constraint_layout.xml"
+ line="224"
+ column="9"
+ message="Occurrence in layout-land"/>
+ </issue>
+
+ <issue
+ id="InconsistentLayout"
+ message="The id "volume_dialog_top_container" in layout "volume_dialog" is missing from the following layout configurations: layout-land-television (present in layout, layout-land)"
+ errorLine1=" android:id="@+id/volume_dialog_top_container""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/volume_dialog.xml"
+ line="41"
+ column="13"
+ message="Occurrence in layout"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout-land/volume_dialog.xml"
+ line="42"
+ column="13"
+ message="Occurrence in layout-land"/>
+ </issue>
+
+ <issue
+ id="InconsistentLayout"
+ message="The id "ringer" in layout "volume_dialog" is missing from the following layout configurations: layout-land-television (present in layout, layout-land)"
+ errorLine1=" android:id="@+id/ringer""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/volume_dialog.xml"
+ line="52"
+ column="17"
+ message="Occurrence in layout"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout-land/volume_dialog.xml"
+ line="53"
+ column="17"
+ message="Occurrence in layout-land"/>
+ </issue>
+
+ <issue
+ id="InconsistentLayout"
+ message="The id "ringer_icon" in layout "volume_dialog" is missing from the following layout configurations: layout-land-television (present in layout, layout-land)"
+ errorLine1=" android:id="@+id/ringer_icon""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/volume_dialog.xml"
+ line="62"
+ column="21"
+ message="Occurrence in layout"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout-land/volume_dialog.xml"
+ line="63"
+ column="21"
+ message="Occurrence in layout-land"/>
+ </issue>
+
+ <issue
+ id="InconsistentLayout"
+ message="The id "settings_container" in layout "volume_dialog" is missing from the following layout configurations: layout-land-television (present in layout, layout-land)"
+ errorLine1=" android:id="@+id/settings_container""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/volume_dialog.xml"
+ line="92"
+ column="21"
+ message="Occurrence in layout"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout-land/volume_dialog.xml"
+ line="93"
+ column="21"
+ message="Occurrence in layout-land"/>
+ </issue>
+
+ <issue
+ id="InconsistentLayout"
+ message="The id "settings" in layout "volume_dialog" is missing from the following layout configurations: layout-land-television (present in layout, layout-land)"
+ errorLine1=" android:id="@+id/settings""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/volume_dialog.xml"
+ line="100"
+ column="25"
+ message="Occurrence in layout"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout-land/volume_dialog.xml"
+ line="101"
+ column="25"
+ message="Occurrence in layout-land"/>
+ </issue>
+
+ <issue
+ id="InconsistentLayout"
+ message="The id "volume_number" in layout "volume_dialog_row" is missing from the following layout configurations: layout (present in layout-land-television)"
+ errorLine1=" android:id="@+id/volume_number""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml"
+ line="36"
+ column="13"
+ message="Occurrence in layout-land-television"/>
+ </issue>
+
+ <issue
+ id="KotlinNullnessAnnotation"
+ message="Do not use `@NonNull` in Kotlin; the nullability is already implied by the Kotlin type `PrintWriter` **not** ending with `?`"
+ errorLine1=" fun dump(@NonNull pw: PrintWriter, name: String) {"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt"
+ line="112"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The color "notification_primary_text_color" in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <color name="notification_primary_text_color">@*android:color/notification_primary_text_color_dark</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+ line="34"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The color "notification_section_header_label_color" in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <color name="notification_section_header_label_color">@color/GM2_grey_200</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+ line="45"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The color "notification_channel_dialog_separator" in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <color name="notification_channel_dialog_separator">@color/GM2_grey_700</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+ line="47"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The color "global_actions_text" in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <color name="global_actions_text">@color/GM2_grey_200</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+ line="56"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The color "global_actions_alert_text" in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <color name="global_actions_alert_text">@color/GM2_red_300</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+ line="59"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The color "media_divider" in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <color name="media_divider">#85ffffff</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+ line="65"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The color "GM2_green_500" in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <color name="GM2_green_500">#FF41Af6A</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+ line="81"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The color "GM2_blue_500" in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <color name="GM2_blue_500">#5195EA</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+ line="82"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The color "GM2_yellow_500" in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <color name="GM2_yellow_500">#F5C518</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+ line="84"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The color "kg_user_switcher_selected_avatar_icon_color" in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <color name="kg_user_switcher_selected_avatar_icon_color">#202124</color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-night/colors.xml"
+ line="89"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The bool "quick_settings_rssi_tile_capitalization" in values-mcc262-mnc07 has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <bool name="quick_settings_rssi_tile_capitalization">false</bool>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mcc262-mnc07/config.xml"
+ line="24"
+ column="11"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The bool "quick_settings_rssi_tile_capitalization" in values-mcc262-mnc08 has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <bool name="quick_settings_rssi_tile_capitalization">false</bool>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mcc262-mnc08/config.xml"
+ line="24"
+ column="11"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The bool "quick_settings_rssi_tile_capitalization" in values-mcc262-mnc11 has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <bool name="quick_settings_rssi_tile_capitalization">false</bool>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mcc262-mnc11/config.xml"
+ line="24"
+ column="11"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The integer "quick_settings_user_time_settings_tile_span" in values-land has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <integer name="quick_settings_user_time_settings_tile_span">2</integer>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-land/config.xml"
+ line="29"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The integer "power_menu_max_columns" in values-land has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <integer name="power_menu_max_columns">4</integer>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-land/config.xml"
+ line="35"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The dimen "ambient_indication_container_margin_top" in values-h700dp has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <dimen name="ambient_indication_container_margin_top">15dp</dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-h700dp/dimens.xml"
+ line="19"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The dimen "ambient_indication_container_margin_top" in values-h800dp has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <dimen name="ambient_indication_container_margin_top">20dp</dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-h800dp/dimens.xml"
+ line="19"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The dimen "volume_dialog_panel_height" in values-land-television has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <dimen name="volume_dialog_panel_height">190dp</dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-land-television/dimens.xml"
+ line="19"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The dimen "screenshot_bg_protection_height" in values-night has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <dimen name="screenshot_bg_protection_height">375dp</dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-night/dimens.xml"
+ line="21"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The dimen "docked_divider_handle_width" in values-land has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <dimen name="docked_divider_handle_width">2dp</dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-land/dimens.xml"
+ line="22"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The dimen "docked_divider_handle_height" in values-land has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <dimen name="docked_divider_handle_height">16dp</dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-land/dimens.xml"
+ line="23"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The dimen "button_size" in values-sw900dp has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <dimen name="button_size">80dp</dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw900dp/dimens.xml"
+ line="26"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The dimen "tv_volume_dialog_bubble_size" in values-land-television has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <dimen name="tv_volume_dialog_bubble_size">36dp</dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-land-television/dimens.xml"
+ line="28"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The dimen "tv_volume_dialog_row_padding" in values-land-television has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <dimen name="tv_volume_dialog_row_padding">6dp</dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-land-television/dimens.xml"
+ line="29"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The dimen "tv_volume_number_text_size" in values-land-television has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <dimen name="tv_volume_number_text_size">16sp</dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-land-television/dimens.xml"
+ line="30"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The dimen "tv_volume_seek_bar_thumb_diameter" in values-land-television has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <dimen name="tv_volume_seek_bar_thumb_diameter">16dp</dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-land-television/dimens.xml"
+ line="31"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The dimen "tv_volume_icons_size" in values-land-television has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <dimen name="tv_volume_icons_size">20dp</dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-land-television/dimens.xml"
+ line="32"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The dimen "volume_tool_tip_top_margin" in values-land has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <dimen name="volume_tool_tip_top_margin">12dp</dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-land/dimens.xml"
+ line="35"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The dimen "controls_activity_view_top_offset" in values-land has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <dimen name="controls_activity_view_top_offset">25dp</dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-land/dimens.xml"
+ line="41"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingDefaultResource"
+ message="The dimen "car_body2_size" in values-h600dp has no declaration in the base `values` folder; this can lead to crashes when the resource is queried in a configuration that does not match this qualifier"
+ errorLine1=" <dimen name="car_body2_size">32sp</dimen> <!-- B2 -->"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-h600dp/dimens_car.xml"
+ line="19"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="MissingPrefix"
+ message="Attribute is missing the Android namespace prefix"
+ errorLine1=" <item android:state_activated="true" android_state_enabled="true" android:color="@color/kg_user_switcher_activated_background_color" />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/color/kg_user_switcher_rounded_background_color.xml"
+ line="20"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="SdCardPath"
+ message="Do not hardcode "/sdcard/"; use `Environment.getExternalStorageDirectory().getPath()` instead"
+ errorLine1=" ? new GestureRecorder("/sdcard/statusbar_gestures.dat")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+ line="467"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="ShowToast"
+ message="Expected duration `Toast.LENGTH_SHORT` or `Toast.LENGTH_LONG`, a custom duration value is not supported"
+ errorLine1=" 500).show();"
+ errorLine2=" ~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java"
+ line="1894"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="SimpleDateFormat"
+ message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+ errorLine1=" private static final SimpleDateFormat SSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/CallbackHandler.java"
+ line="52"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="SimpleDateFormat"
+ message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+ errorLine1=" mContentDescriptionFormat = new SimpleDateFormat(format);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java"
+ line="452"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="SimpleDateFormat"
+ message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+ errorLine1=" mClockFormat = new SimpleDateFormat(format);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java"
+ line="483"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="SimpleDateFormat"
+ message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+ errorLine1=" private static final SimpleDateFormat SSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java"
+ line="60"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="SimpleDateFormat"
+ message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+ errorLine1=" private static final SimpleDateFormat SSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+ line="119"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="SimpleDateFormat"
+ message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+ errorLine1=" String today = new SimpleDateFormat("MM-dd").format(new Date());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java"
+ line="503"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="SimpleDateFormat"
+ message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates."
+ errorLine1=" String fileName = new SimpleDateFormat("'screen-'yyyyMMdd-HHmmss'.mp4'")"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java"
+ line="329"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="Slices"
+ message="A slice should have a primary action set on one of its rows"
+ errorLine1=" ListBuilder builder = new ListBuilder(getContext(), mSliceUri, ListBuilder.INFINITY);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java"
+ line="218"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="ValidFragment"
+ message="This fragment should provide a default constructor (a public constructor with no arguments) (`com.android.systemui.tuner.DemoModeFragment`)"
+ errorLine1="public class DemoModeFragment extends PreferenceFragment implements OnPreferenceChangeListener {"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+ line="38"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ValidFragment"
+ message="This fragment should provide a default constructor (a public constructor with no arguments) (`com.android.systemui.qs.QSFragmentLegacy`)"
+ errorLine1="public class QSFragmentLegacy extends LifecycleFragment implements QS {"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java"
+ line="42"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ValidFragment"
+ message="Avoid non-default constructors in fragments: use a default constructor plus `Fragment#setArguments(Bundle)` instead"
+ errorLine1=" public QSFragmentLegacy("
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSFragmentLegacy.java"
+ line="52"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="ValidFragment"
+ message="This fragment should provide a default constructor (a public constructor with no arguments) (`com.android.systemui.tuner.TunerFragment`)"
+ errorLine1="public class TunerFragment extends PreferenceFragment {"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java"
+ line="41"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+ errorLine1=" animateAway(false /* sendReason */, 0 /* reason */);"
+ errorLine2=" ~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java"
+ line="778"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+ errorLine1=" animateAway(false /* sendReason */, 0 /* reason */);"
+ errorLine2=" ~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java"
+ line="787"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+ errorLine1=" sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_USER_CANCEL,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+ line="539"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+ errorLine1=" sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_NEGATIVE,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+ line="544"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+ errorLine1=" sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+ line="549"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+ errorLine1=" BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+ line="555"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+ errorLine1=" sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_ERROR,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+ line="560"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+ errorLine1=" sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_SERVER_REQUESTED,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+ line="565"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+ errorLine1=" sendResultAndCleanUp(BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+ line="570"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: AuthDialogCallback.DISMISSED_USER_CANCELED, AuthDialogCallback.DISMISSED_BUTTON_NEGATIVE, AuthDialogCallback.DISMISSED_BUTTON_POSITIVE, AuthDialogCallback.DISMISSED_BIOMETRIC_AUTHENTICATED, AuthDialogCallback.DISMISSED_ERROR, AuthDialogCallback.DISMISSED_BY_SYSTEM_SERVER, AuthDialogCallback.DISMISSED_CREDENTIAL_AUTHENTICATED, AuthDialogCallback.DISMISSED_BUTTON_CONTENT_VIEW_MORE_OPTIONS"
+ errorLine1=" BiometricPrompt.DISMISSED_REASON_CONTENT_VIEW_MORE_OPTIONS,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+ line="576"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS, DreamOverlayStatusBarView.STATUS_ICON_WIFI_UNAVAILABLE, DreamOverlayStatusBarView.STATUS_ICON_ALARM_SET, DreamOverlayStatusBarView.STATUS_ICON_CAMERA_DISABLED, DreamOverlayStatusBarView.STATUS_ICON_MIC_DISABLED, DreamOverlayStatusBarView.STATUS_ICON_MIC_CAMERA_DISABLED, DreamOverlayStatusBarView.STATUS_ICON_PRIORITY_MODE_ON, DreamOverlayStatusBarView.STATUS_ICON_ASSISTANT_ATTENTION_ACTIVE"
+ errorLine1=" @DreamOverlayStatusBarView.StatusIconType int iconType = Resources.ID_NULL;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java"
+ line="287"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" @MediaLocation private var desiredLocation: Int = -1"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+ line="153"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" @MediaLocation @VisibleForTesting var currentEndLocation: Int = -1"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+ line="159"
+ column="69"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" @MediaLocation private var currentStartLocation: Int = -1"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+ line="165"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (location == desiredLocation) {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+ line="542"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" onDesiredLocationChanged(desiredLocation, mediaHostState, animate = false)"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+ line="543"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" startLocation != currentStartLocation ||"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+ line="974"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentStartLocation = startLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+ line="979"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" val startIsVisible = hostStates[currentStartLocation]?.visible ?: false"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+ line="994"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" hostStates[currentStartLocation]?.showsOnlyActiveMedia ?: endShowsActive"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+ line="1070"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" startLocation = currentStartLocation,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+ line="1085"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" startLocation = currentStartLocation,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+ line="1085"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (this.desiredLocation != desiredLocation) {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+ line="1111"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" this.desiredLocation = desiredLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+ line="1117"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" println("location: $desiredLocation")"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt"
+ line="1325"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" @MediaLocation private var crossFadeAnimationStartLocation = -1"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="155"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" @MediaLocation private var crossFadeAnimationEndLocation = -1"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="158"
+ column="64"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" @MediaLocation private var previousLocation = -1"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="226"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" @MediaLocation private var desiredLocation = -1"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="228"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" @MediaLocation private var currentAttachmentLocation = -1"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="235"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" val startHost = getHost(previousLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="337"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" val startHost = getHost(previousLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="337"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (mediaObject.location == desiredLocation) {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="618"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" desiredLocation = -1"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="621"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" desiredLocation = -1"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="621"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (mediaObject.location == currentAttachmentLocation) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="623"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentAttachmentLocation = -1"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="624"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentAttachmentLocation = -1"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="624"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" desiredLocation != this.desiredLocation || forceStateUpdate && !blockLocationChanges"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="671"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (this.desiredLocation >= 0 && desiredLocation != this.desiredLocation) {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="673"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (this.desiredLocation >= 0 && desiredLocation != this.desiredLocation) {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="673"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" previousLocation = this.desiredLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="675"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" previousLocation = this.desiredLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="675"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" previousLocation = this.desiredLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="675"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" previousLocation == LOCATION_LOCKSCREEN &&"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="682"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" previousLocation = LOCATION_QQS"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="687"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" val isNewView = this.desiredLocation == -1"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="690"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" this.desiredLocation = desiredLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="691"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" !forceNoAnimation && shouldAnimateTransition(desiredLocation, previousLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="694"
+ column="83"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" !forceNoAnimation && shouldAnimateTransition(desiredLocation, previousLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="694"
+ column="83"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" val (animDuration, delay) = getAnimationParams(previousLocation, desiredLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="695"
+ column="64"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (previousLocation < 0 || isNewView) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="715"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" val currentHost = getHost(desiredLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="719"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" val currentHost = getHost(desiredLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="719"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" val previousHost = getHost(previousLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="720"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" val previousHost = getHost(previousLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="720"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentAttachmentLocation != previousLocation ||"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="733"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentAttachmentLocation != previousLocation ||"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="733"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" var newCrossFadeStartLocation = previousLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="751"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (currentAttachmentLocation == crossFadeAnimationEndLocation) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="753"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (currentAttachmentLocation == crossFadeAnimationEndLocation) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="753"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" newCrossFadeStartLocation = crossFadeAnimationStartLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="763"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (newCrossFadeStartLocation == desiredLocation) {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="764"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" crossFadeAnimationStartLocation = newCrossFadeStartLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="781"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" crossFadeAnimationStartLocation = newCrossFadeStartLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="781"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" crossFadeAnimationEndLocation = desiredLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="782"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" crossFadeAnimationEndLocation = desiredLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="782"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" crossFadeAnimationEndLocation = desiredLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="782"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" adjustAnimatorForTransition(desiredLocation, previousLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="785"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" adjustAnimatorForTransition(desiredLocation, previousLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="785"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" desiredLocation == LOCATION_QQS &&"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="812"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" desiredLocation == LOCATION_QS &&"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="830"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" var starthost = getHost(previousLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="887"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" var starthost = getHost(previousLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="887"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" var endHost = getHost(desiredLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="888"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" var endHost = getHost(desiredLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="888"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" return previousLocation != -1 && desiredLocation != -1"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="943"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" return previousLocation != -1 && desiredLocation != -1"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="943"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" previousLocation == LOCATION_LOCKSCREEN && desiredLocation == LOCATION_QS ||"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="957"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" previousLocation == LOCATION_LOCKSCREEN && desiredLocation == LOCATION_QS ||"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="957"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" previousLocation == LOCATION_QS && desiredLocation == LOCATION_LOCKSCREEN"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="958"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" previousLocation == LOCATION_QS && desiredLocation == LOCATION_LOCKSCREEN"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="958"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (previousLocation == LOCATION_LOCKSCREEN && desiredLocation == LOCATION_QQS) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="963"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (previousLocation == LOCATION_LOCKSCREEN && desiredLocation == LOCATION_QQS) {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="963"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" return getHost(previousLocation)?.visible == true &&"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="971"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" return getHost(previousLocation)?.visible == true &&"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="971"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" getHost(desiredLocation)?.visible == true"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="972"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" getHost(desiredLocation)?.visible == true"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="972"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" val currentHost = getHost(desiredLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="994"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" val currentHost = getHost(desiredLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="994"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" val previousHost = getHost(previousLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="995"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" val previousHost = getHost(previousLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="995"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" getHost(desiredLocation)?.let {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1015"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" getHost(desiredLocation)?.let {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1015"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" val startLocation = if (onlyUseEndState) -1 else previousLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1032"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" startLocation,"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1036"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" startLocation,"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1036"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (currentAttachmentLocation == IN_OVERLAY) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1042"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" logger.logMediaHostAttachment(desiredLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1060"
+ column="47"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" desiredLocation = desiredLocation,"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1062"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" desiredHostState = getHost(desiredLocation),"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1063"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" desiredHostState = getHost(desiredLocation),"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1063"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" newLocation != desiredLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1076"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (currentAttachmentLocation != newLocation) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1085"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentAttachmentLocation = newLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1086"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentAttachmentLocation = newLocation"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1086"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" val targetHost = getHost(newLocation)!!.hostView"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1095"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" logger.logMediaHostAttachment(currentAttachmentLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1100"
+ column="47"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" getHost(newLocation),"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1111"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (animationCrossFadeProgress > 0.5 || previousLocation == -1) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1127"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" return crossFadeAnimationEndLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1128"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" return crossFadeAnimationStartLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1130"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" return desiredLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1133"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" return desiredLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1146"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" return desiredLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1146"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" mediaFlags.isSceneContainerEnabled() -> desiredLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1152"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" desiredLocation == LOCATION_QS &&"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1179"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" location != LOCATION_LOCKSCREEN && desiredLocation == LOCATION_LOCKSCREEN && !fullyAwake"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHierarchyManager.kt"
+ line="1186"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" @MediaLocation var currentEndLocation: Int = -1"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="121"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" @MediaLocation private var currentStartLocation: Int = -1"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="124"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" if (location == currentEndLocation || location == currentStartLocation) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="287"
+ column="67"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentStartLocation,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="289"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentStartLocation,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="289"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentStartLocation,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="351"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentStartLocation,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="351"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentStartLocation,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="372"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentStartLocation,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="372"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentStartLocation,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="372"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentStartLocation,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="372"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" logger.logMediaLocation("attach $type", currentStartLocation, currentEndLocation)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="640"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" startLocation = currentStartLocation,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="648"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" startLocation = currentStartLocation,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="648"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentStartLocation = startLocation"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="854"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentStartLocation,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="1076"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: MediaHierarchyManager.LOCATION_QS, MediaHierarchyManager.LOCATION_QQS, MediaHierarchyManager.LOCATION_LOCKSCREEN, MediaHierarchyManager.LOCATION_DREAM_OVERLAY, MediaHierarchyManager.LOCATION_COMMUNAL_HUB"
+ errorLine1=" currentStartLocation,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt"
+ line="1076"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one or more of: NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED, NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED, NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP, NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC, NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE, NotificationRowContentBinder.FLAG_GROUP_SUMMARY_HEADER, NotificationRowContentBinder.FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER, NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL"
+ errorLine1=" freeNotificationView(entry, row, curFlag);"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java"
+ line="250"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one or more of: NotificationRowContentBinder.FLAG_CONTENT_VIEW_CONTRACTED, NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED, NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP, NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC, NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE, NotificationRowContentBinder.FLAG_GROUP_SUMMARY_HEADER, NotificationRowContentBinder.FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER, NotificationRowContentBinder.FLAG_CONTENT_VIEW_ALL"
+ errorLine1=" contentToUnbind &= ~curFlag;"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java"
+ line="252"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" private @Action int mSelectedAction = -1;"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="116"
+ column="43"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" updateToggleActions(mSelectedAction, true);"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="142"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" updateToggleActions(mSelectedAction, true);"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="147"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" updateToggleActions(mSelectedAction, true);"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="152"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" if (mSelectedAction == ACTION_FAVORITE && getPriority() != mSelectedAction) {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="160"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" if (mSelectedAction == ACTION_FAVORITE && getPriority() != mSelectedAction) {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="160"
+ column="68"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" if (mSelectedAction == selectedAction) {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="187"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" mSelectedAction = selectedAction;"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="191"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" updateToggleActions(mSelectedAction == -1 ? getPriority() : mSelectedAction,"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="292"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" updateToggleActions(mSelectedAction == -1 ? getPriority() : mSelectedAction,"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="292"
+ column="69"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" throw new IllegalArgumentException("Unrecognized behavior: " + mSelectedAction);"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="500"
+ column="80"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" return mSelectedAction;"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="514"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" mAppUid, mSelectedAction, mNotificationChannel));"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="532"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" mAppUid, mSelectedAction, mNotificationChannel));"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="532"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" if (save && mSelectedAction > -1) {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="579"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" mSelectedAction = -1;"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="585"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: NotificationConversationInfo.ACTION_DEFAULT, NotificationConversationInfo.ACTION_HOME, NotificationConversationInfo.ACTION_FAVORITE, NotificationConversationInfo.ACTION_SNOOZE, NotificationConversationInfo.ACTION_MUTE, NotificationConversationInfo.ACTION_SETTINGS"
+ errorLine1=" mSelectedAction = -1;"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="585"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, Key.DEBUG_MODE_ENABLED, Key.HOTSPOT_TILE_LAST_USED, Key.COLOR_INVERSION_TILE_LAST_USED, Key.DND_TILE_VISIBLE, Key.DND_TILE_COMBINED_ICON, Key.DND_CONFIRMED_PRIORITY_INTRODUCTION, Key.DND_CONFIRMED_SILENCE_INTRODUCTION, Key.DND_FAVORITE_BUCKET_INDEX, Key.DND_NONE_SELECTED, Key.DND_FAVORITE_ZEN, Key.QS_HOTSPOT_ADDED, Key.QS_DATA_SAVER_ADDED, Key.QS_DATA_SAVER_DIALOG_SHOWN, Key.QS_INVERT_COLORS_ADDED, Key.QS_WORK_ADDED, Key.QS_NIGHTDISPLAY_ADDED, Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT, Key.SEEN_RINGER_GUIDANCE_COUNT, Key.QS_HAS_TURNED_OFF_MOBILE_DATA, Key.TOUCHED_RINGER_TOGGLE, Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP, Key.HAS_SEEN_REVERSE_BOTTOM_SHEET, Key.CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT, Key.HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP, Key.ACCESSIBILITY_FLOATING_MENU_POSITION, Key.HAS_CLICKED_NUDGE_TO_SETUP_DREAM, Key.HAS_DISMISSED_NUDGE_TO_SETUP_DREAM, Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED, Key.BLUETOOTH_TILE_DIALOG_CONTENT_HEIGHT"
+ errorLine1=" mContext, QS_TILE_SPECS_REVEALED, Collections.EMPTY_SET);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java"
+ line="73"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, Key.DEBUG_MODE_ENABLED, Key.HOTSPOT_TILE_LAST_USED, Key.COLOR_INVERSION_TILE_LAST_USED, Key.DND_TILE_VISIBLE, Key.DND_TILE_COMBINED_ICON, Key.DND_CONFIRMED_PRIORITY_INTRODUCTION, Key.DND_CONFIRMED_SILENCE_INTRODUCTION, Key.DND_FAVORITE_BUCKET_INDEX, Key.DND_NONE_SELECTED, Key.DND_FAVORITE_ZEN, Key.QS_HOTSPOT_ADDED, Key.QS_DATA_SAVER_ADDED, Key.QS_DATA_SAVER_DIALOG_SHOWN, Key.QS_INVERT_COLORS_ADDED, Key.QS_WORK_ADDED, Key.QS_NIGHTDISPLAY_ADDED, Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT, Key.SEEN_RINGER_GUIDANCE_COUNT, Key.QS_HAS_TURNED_OFF_MOBILE_DATA, Key.TOUCHED_RINGER_TOGGLE, Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP, Key.HAS_SEEN_REVERSE_BOTTOM_SHEET, Key.CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT, Key.HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP, Key.ACCESSIBILITY_FLOATING_MENU_POSITION, Key.HAS_CLICKED_NUDGE_TO_SETUP_DREAM, Key.HAS_DISMISSED_NUDGE_TO_SETUP_DREAM, Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED, Key.BLUETOOTH_TILE_DIALOG_CONTENT_HEIGHT"
+ errorLine1=" Prefs.getStringSet(mContext, QS_TILE_SPECS_REVEALED, Collections.EMPTY_SET));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java"
+ line="87"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="WrongConstant"
+ message="Must be one of: Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, Key.DEBUG_MODE_ENABLED, Key.HOTSPOT_TILE_LAST_USED, Key.COLOR_INVERSION_TILE_LAST_USED, Key.DND_TILE_VISIBLE, Key.DND_TILE_COMBINED_ICON, Key.DND_CONFIRMED_PRIORITY_INTRODUCTION, Key.DND_CONFIRMED_SILENCE_INTRODUCTION, Key.DND_FAVORITE_BUCKET_INDEX, Key.DND_NONE_SELECTED, Key.DND_FAVORITE_ZEN, Key.QS_HOTSPOT_ADDED, Key.QS_DATA_SAVER_ADDED, Key.QS_DATA_SAVER_DIALOG_SHOWN, Key.QS_INVERT_COLORS_ADDED, Key.QS_WORK_ADDED, Key.QS_NIGHTDISPLAY_ADDED, Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT, Key.SEEN_RINGER_GUIDANCE_COUNT, Key.QS_HAS_TURNED_OFF_MOBILE_DATA, Key.TOUCHED_RINGER_TOGGLE, Key.HAS_SEEN_ODI_CAPTIONS_TOOLTIP, Key.HAS_SEEN_REVERSE_BOTTOM_SHEET, Key.CONTROLS_STRUCTURE_SWIPE_TOOLTIP_COUNT, Key.HAS_SEEN_ACCESSIBILITY_FLOATING_MENU_DOCK_TOOLTIP, Key.ACCESSIBILITY_FLOATING_MENU_POSITION, Key.HAS_CLICKED_NUDGE_TO_SETUP_DREAM, Key.HAS_DISMISSED_NUDGE_TO_SETUP_DREAM, Key.HAS_ACCESSIBILITY_FLOATING_MENU_TUCKED, Key.BLUETOOTH_TILE_DIALOG_CONTENT_HEIGHT"
+ errorLine1=" Prefs.putStringSet(mContext, QS_TILE_SPECS_REVEALED, revealedTiles);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java"
+ line="89"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="WrongThread"
+ message="Method notifyContentChanged must be called from the UI thread, currently inferred thread is any thread"
+ errorLine1=" notifyContentChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/ImageTileSet.java"
+ line="90"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="IncludeLayoutParam"
+ message="Layout parameter `layout_weight` ignored unless both `layout_width` and `layout_height` are also specified on `<include>` tag"
+ errorLine1=" android:layout_weight="1"/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/shade_carrier_group.xml"
+ line="44"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="IncludeLayoutParam"
+ message="Layout parameter `layout_weight` ignored unless both `layout_width` and `layout_height` are also specified on `<include>` tag"
+ errorLine1=" android:layout_weight="1""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/shade_carrier_group.xml"
+ line="56"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="IncludeLayoutParam"
+ message="Layout parameter `layout_weight` ignored unless both `layout_width` and `layout_height` are also specified on `<include>` tag"
+ errorLine1=" android:layout_weight="1""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/shade_carrier_group.xml"
+ line="70"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" mLayout = getLayoutInflater().inflate(R.layout.app_clips_screenshot, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java"
+ line="149"
+ column="78"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.biometric_prompt_layout, null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java"
+ line="451"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.auth_credential_pattern_view, null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java"
+ line="497"
+ column="64"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" mCredentialView = factory.inflate(R.layout.auth_credential_pin_view, null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java"
+ line="500"
+ column="86"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.auth_credential_password_view, null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java"
+ line="504"
+ column="65"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" .inflate(R.layout.battery_percentage_view, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/battery/BatteryMeterView.java"
+ line="377"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" return inflater.inflate(R.layout.biometric_prompt_content_row_layout, null) as LinearLayout"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricCustomizedViewBinder.kt"
+ line="161"
+ column="75"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" inflater.inflate(R.layout.biometric_prompt_content_row_item_text_view, null) as TextView"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricCustomizedViewBinder.kt"
+ line="219"
+ column="80"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" LayoutInflater.from(context).inflate(R.layout.bluetooth_tile_dialog, null).apply {"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt"
+ line="115"
+ column="78"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" (LayoutInflater.from(context).inflate(R.layout.brightness_mirror_container, null)"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/settings/brightness/ui/binder/BrightnessMirrorInflater.kt"
+ line="34"
+ column="89"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" View dialogView = dialog.getLayoutInflater().inflate(R.layout.broadcast_dialog, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java"
+ line="201"
+ column="89"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" setView(LayoutInflater.from(context).inflate(R.layout.controls_dialog_pin, null))"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt"
+ line="87"
+ column="88"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" val row = inflater.inflate(R.layout.notif_half_shelf_row, null) as ChannelRow"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt"
+ line="123"
+ column="67"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.clipboard_overlay, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/clipboardoverlay/dagger/ClipboardOverlayModule.java"
+ line="61"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" null),"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/complication/dagger/ComplicationHostViewModule.java"
+ line="65"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" dialogView = dialog.layoutInflater.inflate(R.layout.contrast_dialog, null)"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/contrast/ContrastDialogDelegate.kt"
+ line="54"
+ column="78"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" /* root = */ null,"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamClockTimeComplicationComponent.kt"
+ line="71"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamHomeControlsComplicationComponent.java"
+ line="90"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" return (View) layoutInflater.inflate(R.layout.dream_overlay_media_entry_chip, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/complication/dagger/DreamMediaEntryComplicationComponent.java"
+ line="78"
+ column="91"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" layoutInflater.inflate(R.layout.dream_overlay_container, null),"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java"
+ line="61"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" dialog.setView(layoutInflater.inflate(R.layout.font_scaling_dialog, null))"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/fontscaling/FontScalingDialogDelegate.kt"
+ line="85"
+ column="77"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" .inflate(R.layout.fullscreen_magnification_border, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/FullscreenMagnificationController.java"
+ line="181"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" com.android.systemui.res.R.layout.global_actions_power_dialog, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsPowerDialog.java"
+ line="39"
+ column="80"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.hearing_devices_tile_dialog, null));"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesDialogDelegate.java"
+ line="235"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.internet_connectivity_dialog, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java"
+ line="231"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.keyboard_shortcuts_search_view, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java"
+ line="861"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.keyboard_shortcuts_key_view, null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java"
+ line="626"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" return inflater.inflate(R.layout.notification_icon_area, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyNotificationIconAreaControllerImpl.java"
+ line="163"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" LayoutInflater.from(context).inflate(R.layout.screenshot, null) as ScreenshotView"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/LegacyScreenshotViewProxy.kt"
+ line="57"
+ column="67"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.log_access_user_consent_dialog_permission, null /*root*/);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/logcat/LogAccessDialogActivity.java"
+ line="208"
+ column="69"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" mDialogView = LayoutInflater.from(mContext).inflate(R.layout.media_output_dialog, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java"
+ line="246"
+ column="91"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaSessionReleaseDialog.java"
+ line="67"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" return (NavigationBarFrame) layoutInflater.inflate(R.layout.navigation_bar_window, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarModule.java"
+ line="47"
+ column="92"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" .inflate(R.layout.notification_snooze, null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java"
+ line="1592"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" .inflate(R.layout.notification_snooze, null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java"
+ line="663"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.notification_conversation_info, null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java"
+ line="675"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.partial_conversation_info, null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java"
+ line="685"
+ column="61"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.notification_info, null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java"
+ line="694"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.feedback_info, null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java"
+ line="701"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.keyguard_pin_shape_hinting_view, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java"
+ line="153"
+ column="63"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.keyguard_pin_shape_non_hinting_view, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/PasswordTextView.java"
+ line="156"
+ column="67"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" .inflate(R.layout.people_space_activity, /* root= */ null) as ViewGroup"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/ui/view/PeopleViewBinder.kt"
+ line="66"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" inflater.inflate(R.layout.qs_panel, null) { view, _, _ ->"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt"
+ line="262"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" .inflate(R.layout.quick_settings_footer_dialog, null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java"
+ line="497"
+ column="65"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" .inflate(R.layout.quick_settings_footer_dialog_parental_controls, null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java"
+ line="585"
+ column="83"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" dialogView = inflater.inflate(R.layout.activity_rear_display_education, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/reardisplay/RearDisplayDialogController.java"
+ line="145"
+ column="85"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.activity_rear_display_education_opened, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/reardisplay/RearDisplayDialogController.java"
+ line="148"
+ column="70"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" setView(LayoutInflater.from(context).inflate(R.layout.record_issue_dialog, null))"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/recordissue/RecordIssueDialogDelegate.kt"
+ line="84"
+ column="88"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.screen_decor_hwc_layer, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java"
+ line="846"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" .inflate(R.layout.screen_record_dialog_audio_source, null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordingAdapter.java"
+ line="55"
+ column="70"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" .inflate(R.layout.screen_record_dialog_audio_source_selected, null, false);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordingAdapter.java"
+ line="71"
+ column="79"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" LayoutInflater.from(context).inflate(R.layout.screenshot_shelf, null) as ScreenshotShelfView"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt"
+ line="63"
+ column="73"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" val view = layoutInflater.inflate(R.layout.sidefps_view, null, false)"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt"
+ line="298"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" overlayView = layoutInflater.get().inflate(R.layout.sidefps_view, null, false)"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt"
+ line="125"
+ column="75"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" final View view = layoutInflater.inflate(R.layout.magnifier_controllers, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/SimpleMirrorWindowControl.java"
+ line="68"
+ column="82"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" return LayoutInflater.from(context).inflate(R.layout.bindable_status_bar_icon, null)"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/view/SingleBindableStatusBarIconView.kt"
+ line="69"
+ column="92"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.smart_reply_view, null /* root */);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java"
+ line="150"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" /* root= */null"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt"
+ line="27"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" /* root= */null"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt"
+ line="27"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" .inflate(R.layout.system_event_animation_window, null) as FrameLayout"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt"
+ line="242"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" com.android.systemui.res.R.layout.text_toast, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java"
+ line="173"
+ column="67"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" .inflate(R.layout.tile_service_request_dialog, null)"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt"
+ line="51"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" LayoutInflater.from(context).inflate(R.layout.controls_onboarding, null) as ViewGroup"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/TooltipManager.kt"
+ line="64"
+ column="76"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.udfps_touch_overlay, null, false"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt"
+ line="212"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" R.layout.udfps_view, null, false"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt"
+ line="238"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" LayoutInflater.from(this.context).inflate(R.layout.qs_user_dialog_content, null)"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitchDialog.kt"
+ line="59"
+ column="88"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" .inflate(R.layout.qs_user_dialog_content, null)"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt"
+ line="92"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" LayoutInflater.from(this.context).inflate(R.layout.user_switcher_fullscreen, null)"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/UserSwitcherFullscreenDialog.kt"
+ line="49"
+ column="90"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" /* parent= */ null"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt"
+ line="231"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialog.java"
+ line="99"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" mMirrorView = LayoutInflater.from(mContext).inflate(R.layout.window_magnifier_view, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+ line="692"
+ column="93"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout's root element)"
+ errorLine1=" mMirrorView = LayoutInflater.from(mContext).inflate(R.layout.window_magnifier_view, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+ line="742"
+ column="93"/>
+ </issue>
+
+ <issue
+ id="MissingInflatedId"
+ message="`@layout/controls_management` does not contain a declaration with id `status_message`"
+ errorLine1=" statusText = requireViewById(R.id.status_message)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt"
+ line="261"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="MissingInflatedId"
+ message="`@layout/controls_management` does not contain a declaration with id `structure_page_indicator`"
+ errorLine1=" R.id.structure_page_indicator).apply {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt"
+ line="275"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="MissingInflatedId"
+ message="`@layout/controls_management` does not contain a declaration with id `structure_pager`"
+ errorLine1=" structurePager = requireViewById<ViewPager2>(R.id.structure_pager)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt"
+ line="291"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="MissingInflatedId"
+ message="`@layout/controls_management` does not contain a declaration with id `list`"
+ errorLine1=" recyclerView = requireViewById(R.id.list)"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt"
+ line="107"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="MissingInflatedId"
+ message="`@layout/global_actions_grid_item_v2` does not contain a declaration with id `icon`"
+ errorLine1=" ImageView icon = (ImageView) v.findViewById(R.id.icon);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java"
+ line="1899"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="MissingInflatedId"
+ message="`@layout/global_actions_grid_item_v2` does not contain a declaration with id `message`"
+ errorLine1=" TextView messageView = (TextView) v.findViewById(R.id.message);"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java"
+ line="1900"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="MissingInflatedId"
+ message="`@layout/quick_access_wallet` does not contain a declaration with id `action_bar`"
+ errorLine1=" Toolbar toolbar = findViewById(R.id.action_bar);"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletActivity.java"
+ line="120"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="UnspecifiedRegisterReceiverFlag"
+ message="`this` is missing `RECEIVER_EXPORTED` or `RECEIVER_NOT_EXPORTED` flag for unprotected broadcasts registered for android.intent.action.PROFILE_AVAILABLE, android.intent.action.PROFILE_UNAVAILABLE"
+ errorLine1=" context.registerReceiverForAllUsers(this, filter, null, backgroundHandler)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt"
+ line="148"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="VectorRaster"
+ message="Limit vector icons sizes to 200×200 to keep icon drawing fast; see https://developer.android.com/studio/write/vector-asset-studio#when for more"
+ errorLine1=" android:width="360dp" >"
+ errorLine2=" ~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/indeterminate.xml"
+ line="20"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="VectorRaster"
+ message="Limit vector icons sizes to 200×200 to keep icon drawing fast; see https://developer.android.com/studio/write/vector-asset-studio#when for more"
+ errorLine1=" android:width="340dp""
+ errorLine2=" ~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/vector_drawable_progress_indeterminate_horizontal_trimmed.xml"
+ line="23"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="ObjectAnimatorBinding"
+ message="Could not find property setter method `setLeft` on `java.lang.Object`"
+ errorLine1=" PropertyValuesHolder left = PropertyValuesHolder.ofInt("left", 0, 1);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java"
+ line="330"
+ column="68"/>
+ </issue>
+
+ <issue
+ id="ObjectAnimatorBinding"
+ message="Could not find property setter method `setRight` on `java.lang.Object`"
+ errorLine1=" PropertyValuesHolder right = PropertyValuesHolder.ofInt("right", 0, 1);"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java"
+ line="331"
+ column="69"/>
+ </issue>
+
+ <issue
+ id="UnsupportedChromeOsCameraSystemFeature"
+ message="You should look for any camera available on the device, not just the rear"
+ errorLine1=" mIsCameraAvailable = mContext.getPackageManager().hasSystemFeature("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qrcodescanner/controller/QRCodeScannerController.java"
+ line="239"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" BatteryController bC = new BatteryControllerImpl("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/AospPolicyModule.java"
+ line="51"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" getOrCreateInstanceId().id,"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt"
+ line="83"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" getOrCreateInstanceId().id,"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt"
+ line="83"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within package private scope"
+ errorLine1=" + " active[A2DP]=" + device.isActiveDevice(BluetoothProfile.A2DP)"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+ line="164"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within package private scope"
+ errorLine1=" + " active[HEADSET]=" + device.isActiveDevice(BluetoothProfile.HEADSET)"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+ line="165"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within package private scope"
+ errorLine1=" + " active[HEARING_AID]=" + device.isActiveDevice(BluetoothProfile.HEARING_AID)"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+ line="166"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within package private scope"
+ errorLine1=" + " active[LE_AUDIO]=" + device.isActiveDevice(BluetoothProfile.LE_AUDIO);"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+ line="167"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within package private scope"
+ errorLine1=" isActive |= device.isActiveDevice(BluetoothProfile.HEADSET)"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+ line="294"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within package private scope"
+ errorLine1=" || device.isActiveDevice(BluetoothProfile.A2DP)"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+ line="295"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within package private scope"
+ errorLine1=" || device.isActiveDevice(BluetoothProfile.HEARING_AID)"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+ line="296"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within package private scope"
+ errorLine1=" || device.isActiveDevice(BluetoothProfile.LE_AUDIO);"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java"
+ line="297"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" return calculateLayoutInternal("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerSceneLayout.kt"
+ line="38"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mCentralSurfaces.updateScrimController();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java"
+ line="378"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" instanceId = instanceIdSequence.newInstanceId().id"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLoggerImpl.kt"
+ line="41"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" instanceId = instanceIdSequence.newInstanceId().id"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLoggerImpl.kt"
+ line="41"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This class should only be accessed from tests or within private scope"
+ errorLine1=" controller: ControlsBindingControllerImpl"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt"
+ line="90"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mCentralSurfaces.updateScrimController();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java"
+ line="299"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mCentralSurfaces.updateScrimController();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java"
+ line="306"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mCentralSurfaces.updateScrimController();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java"
+ line="434"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mCentralSurfaces.updateScrimController();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java"
+ line="441"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mDragController.startDragAndDrop(this);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java"
+ line="2084"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" info.setSelectedAction(NotificationConversationInfo.ACTION_FAVORITE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java"
+ line="2132"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" value = foldPostureInternal(layoutInfo)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/fold/ui/composable/FoldPosture.kt"
+ line="41"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" uiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS)"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractor.kt"
+ line="155"
+ column="70"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" if (getCurrentRotation() == ROTATION_NONE) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsColumnLayout.java"
+ line="178"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" switch (getCurrentRotation()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsColumnLayout.java"
+ line="186"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" int rotation = getCurrentRotation();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java"
+ line="135"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" if (getCurrentLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java"
+ line="141"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" switch (getCurrentRotation()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java"
+ line="157"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" if (getCurrentRotation() == ROTATION_NONE) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java"
+ line="169"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mDefaultDataSubId = mInternetDialogController.getDefaultDataSubscriptionId();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java"
+ line="196"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mInternetDialogController.isAirplaneModeEnabled() ? View.VISIBLE : View.GONE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java"
+ line="276"
+ column="43"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mInternetDialogController.isAirplaneModeEnabled() ? View.VISIBLE : View.GONE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java"
+ line="346"
+ column="43"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" if (mInternetDialogController.isAirplaneModeEnabled()) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java"
+ line="531"
+ column="43"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" && mInternetDialogController.isAirplaneModeEnabled();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java"
+ line="833"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" && msgId == BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED; // ran matcher & failed"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java"
+ line="1302"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mUiEventLogger.log(success ? BouncerUiEvent.BOUNCER_PASSWORD_SUCCESS"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+ line="290"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" : BouncerUiEvent.BOUNCER_PASSWORD_FAILURE, getSessionId());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+ line="291"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This class should only be accessed from tests or within private scope"
+ errorLine1=" BouncerUiEvent uiEvent = BouncerUiEvent.UNKNOWN;"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+ line="869"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" BouncerUiEvent uiEvent = BouncerUiEvent.UNKNOWN;"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+ line="869"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" uiEvent = BouncerUiEvent.BOUNCER_DISMISS_EXTENDED_ACCESS;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+ line="877"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" uiEvent = BouncerUiEvent.BOUNCER_DISMISS_BIOMETRIC;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+ line="881"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" uiEvent = BouncerUiEvent.BOUNCER_DISMISS_NONE_SECURITY;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+ line="887"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" uiEvent = BouncerUiEvent.BOUNCER_DISMISS_PASSWORD;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+ line="899"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" uiEvent = BouncerUiEvent.BOUNCER_DISMISS_SIM;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+ line="913"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" if (uiEvent != BouncerUiEvent.UNKNOWN) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+ line="940"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" .getSecurityView(mCurrentSecurityMode, mKeyguardSecurityCallback,"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java"
+ line="1185"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This class should only be accessed from tests or within private scope"
+ errorLine1=" @Nullable private ActivityTransitionAnimator.Runner mRunner;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="3847"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mRunner.onAnimationCancelled();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="3856"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mRunner = mActivityTransitionAnimator.get().createRunner(mActivityLaunchController);"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="3866"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mRunner.onAnimationStart(transit, apps, wallpapers, nonApps, finishedCallback);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="3867"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mKeyguardUpdateMonitor.onFaceAuthenticated(mSelectedUserInteractor.getSelectedUserId(),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/LatencyTester.java"
+ line="90"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mKeyguardUpdateMonitor.onFingerprintAuthenticated("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/LatencyTester.java"
+ line="93"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" return new LeakDetector("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/leak/LeakModule.java"
+ line="33"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" return new LeakDetector(null, null, null, dumpManager);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/leak/LeakModule.java"
+ line="39"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" instanceId = InstanceId.fakeInstanceId(-1),"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt"
+ line="132"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" instanceId = InstanceId.fakeInstanceId(-1),"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt"
+ line="145"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" val instanceId: InstanceId = InstanceId.fakeInstanceId(-1),"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt"
+ line="92"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" val instanceId: InstanceId = InstanceId.fakeInstanceId(-1),"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/shared/model/MediaData.kt"
+ line="92"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" boolean isCurrentSeekbarInvisible = mSeekBar.getVisibility() == View.GONE;"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+ line="150"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" setUpContentDescriptionForView(mSeekBar, device);"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+ line="251"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" setUpContentDescriptionForView(mSeekBar, device);"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+ line="288"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" setUpContentDescriptionForView(mSeekBar, device);"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+ line="297"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" listControllerFactory?.invoke(userHandle) ?: super.createListController(userHandle)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+ line="156"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" val currentListAdapter = mChooserMultiProfilePagerAdapter.activeListAdapter"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+ line="159"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" val currentListAdapter = mChooserMultiProfilePagerAdapter.activeListAdapter"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+ line="159"
+ column="67"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" val currentListAdapter = mChooserMultiProfilePagerAdapter.activeListAdapter"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+ line="159"
+ column="67"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" val userHandle = mMultiProfilePagerAdapter.activeListAdapter.userHandle"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+ line="169"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" val userHandle = mMultiProfilePagerAdapter.activeListAdapter.userHandle"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+ line="169"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" val userHandle = mMultiProfilePagerAdapter.activeListAdapter.userHandle"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+ line="169"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" val userHandle = mMultiProfilePagerAdapter.activeListAdapter.userHandle"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+ line="169"
+ column="70"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" val userHandle = mMultiProfilePagerAdapter.activeListAdapter.userHandle"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+ line="169"
+ column="70"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mMultiProfilePagerAdapter.personalListAdapter.notifyDataSetChanged()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+ line="231"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" private fun hasWorkProfile() = mMultiProfilePagerAdapter.count > 1"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+ line="290"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" for (i in 0 until mMultiProfilePagerAdapter.count) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+ line="373"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mMultiProfilePagerAdapter"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorActivity.kt"
+ line="375"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" targetAppUserHandle = resolverListAdapter.userHandle,"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionBlockerEmptyStateProvider.kt"
+ line="42"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" targetAppUserHandle = resolverListAdapter.userHandle,"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionBlockerEmptyStateProvider.kt"
+ line="42"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" if (now.minus(it.second) <= RESUME_MEDIA_TIMEOUT) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/resume/MediaResumeListener.kt"
+ line="220"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mUiEventLogger.log(KeyButtonView.NavBarButtonEvent.NAVBAR_IME_SWITCHER_BUTTON_TAP);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java"
+ line="1500"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mMobileSignalControllers.valueAt(i).mInflateSignalStrengths ="
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+ line="1367"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" controller.setActivity(TelephonyManager.DATA_ACTIVITY_INOUT);"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+ line="1376"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" controller.setActivity(TelephonyManager.DATA_ACTIVITY_IN);"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+ line="1379"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" controller.setActivity(TelephonyManager.DATA_ACTIVITY_OUT);"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+ line="1382"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+ line="1385"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" controller.setActivity(TelephonyManager.DATA_ACTIVITY_NONE);"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+ line="1389"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" ranking.populate("
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java"
+ line="276"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" proto.instanceId = n.getInstanceId().getId();"
+ errorLine2=" ~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java"
+ line="104"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mQsController.setExpanded(mSplitShadeEnabled);"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java"
+ line="1367"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" if (mQsController.isExpandImmediate() || mQsController.getExpanded()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java"
+ line="2613"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" if (!mQsController.getExpanded() || mQsController.isExpandImmediate()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java"
+ line="2648"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mView.setStatusBarState(mBarState);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java"
+ line="383"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mView.updateFooter();"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java"
+ line="1559"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" getMessagingStyleMessages(notification);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java"
+ line="197"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" getMessagingStyleMessages(notification);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java"
+ line="258"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mPanelViewControllerLazy.get().cancelHeightAnimator();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java"
+ line="951"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mPanelViewControllerLazy.get().notifyExpandingStarted();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsControllerImpl.java"
+ line="1955"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" instanceId = sbn.instanceId?.id,"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt"
+ line="138"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" instanceId = sbn.instanceId?.id,"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/RenderNotificationListInteractor.kt"
+ line="138"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mContext.release();"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java"
+ line="530"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This class should only be accessed from tests or within private scope"
+ errorLine1=" (layoutParams as SmartReplyView.LayoutParams).mButtonType = SmartButtonType.ACTION"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt"
+ line="384"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" (layoutParams as SmartReplyView.LayoutParams).mButtonType = SmartButtonType.ACTION"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt"
+ line="384"
+ column="63"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This class should only be accessed from tests or within private scope"
+ errorLine1=" (layoutParams as SmartReplyView.LayoutParams).mButtonType = SmartButtonType.REPLY"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt"
+ line="465"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" (layoutParams as SmartReplyView.LayoutParams).mButtonType = SmartButtonType.REPLY"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt"
+ line="465"
+ column="63"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" ((TextView) view).nullLayouts();"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java"
+ line="221"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mCentralSurfaces.updateScrimController();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java"
+ line="976"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" mCentralSurfaces.updateScrimController();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java"
+ line="1195"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" final int sessionId = (sessionIdProvider != null) ? sessionIdProvider.getId() : -1;"
+ errorLine2=" ~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java"
+ line="500"
+ column="79"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" udfpsController?.playStartHaptic()"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsHapticsSimulator.kt"
+ line="55"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" udfpsController.mOverlayParams?.scaleFactor?.let { view.setScaleFactor(it) }"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerLegacy.kt"
+ line="558"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" .createRunner(occludeAnimationController)"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerOcclusionManager.kt"
+ line="128"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="VisibleForTests"
+ message="This method should only be accessed from tests or within private scope"
+ errorLine1=" .onAnimationStart("
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/WindowManagerOcclusionManager.kt"
+ line="129"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="ExtraText"
+ message="Unexpected text found in layout file: ">""
+ errorLine1=" >"
+ errorLine2=" ~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/ongoing_privacy_chip.xml"
+ line="28"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ExtraText"
+ message="Unexpected text found in layout file: "->""
+ errorLine1="<merge xmlns:android="http://schemas.android.com/apk/res/android">->"
+ errorLine2=" ~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/qs_customize_panel_content.xml"
+ line="18"
+ column="67"/>
+ </issue>
+
+ <issue
+ id="SpUsage"
+ message="Should use "`sp`" instead of "`dp`" for text sizes (`@dimen/dream_overlay_complication_clock_time_text_size` is defined as `86dp` in `values/dimens.xml`"
+ errorLine1=" android:textSize="@dimen/dream_overlay_complication_clock_time_text_size""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/dream_overlay_complication_clock_time.xml"
+ line="30"
+ column="5"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+ line="1862"
+ column="67"
+ message="This dp dimension is used as a text size"/>
+ </issue>
+
+ <issue
+ id="SpUsage"
+ message="Should use "`sp`" instead of "`dp`" for text sizes"
+ errorLine1=" <item name="android:textSize">36dp</item>"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-land/styles.xml"
+ line="43"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="SpUsage"
+ message="Should use "`sp`" instead of "`dp`" for text sizes"
+ errorLine1=" <item name="android:textSize">36dp</item>"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/styles.xml"
+ line="255"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="SwitchIntDef"
+ message="Switch statement on an `int` with known associated constant missing case `BiometricUnlockController.MODE_DISMISS_BOUNCER`, `BiometricUnlockController.MODE_NONE`, `BiometricUnlockController.MODE_ONLY_WAKE`, `BiometricUnlockController.MODE_SHOW_BOUNCER`, `BiometricUnlockController.MODE_UNLOCK_COLLAPSING`"
+ errorLine1=" switch (mode) {"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+ line="1522"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="SwitchIntDef"
+ message="Switch statement on an `int` with known associated constant missing case `ICON_NONE`"
+ errorLine1=" switch (icon) {"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/LockIconView.java"
+ line="214"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SwitchIntDef"
+ message="Switch statement on an `int` with known associated constant missing case `NotificationConversationInfo.ACTION_HOME`, `NotificationConversationInfo.ACTION_SETTINGS`, `NotificationConversationInfo.ACTION_SNOOZE`"
+ errorLine1=" switch (mAction) {"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java"
+ line="630"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="SwitchIntDef"
+ message="Switch statement on an `int` with known associated constant missing case `NotificationPriorityBucketKt.BUCKET_UNKNOWN`"
+ errorLine1=" switch(bucket) {"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java"
+ line="127"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="DiscouragedApi"
+ message="Should not restrict activity to fixed orientation. This may not be suitable for different form factors, causing the app to be letterboxed."
+ errorLine1=" <activity android:name=".DessertCase" android:exported="true" android:label="@string/dessert_case" android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" android:launchMode="singleInstance" android:screenOrientation="locked" android:process=":sweetsweetdesserts" android:excludeFromRecents="true">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+ line="517"
+ column="209"/>
+ </issue>
+
+ <issue
+ id="DiscouragedApi"
+ message="Activity should not be non-resizable. With this setting, apps cannot be used in multi-window or free form mode."
+ errorLine1=" <activity android:name=".notetask.shortcut.CreateNoteTaskShortcutActivity" android:enabled="false" android:exported="true" android:excludeFromRecents="true" android:resizeableActivity="false" android:theme="@android:style/Theme.NoDisplay" android:label="@string/note_task_button_label" android:icon="@drawable/ic_note_task_shortcut_widget">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+ line="631"
+ column="166"/>
+ </issue>
+
+ <issue
+ id="Orientation"
+ message="No orientation specified, and the default is horizontal. This is a common source of bugs when children are added dynamically."
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screenshot_shelf.xml"
+ line="44"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="PxUsage"
+ message="Avoid using `"px"` as units; use `"dp"` instead"
+ errorLine1=" <dimen name="lock_icon_padding">48px</dimen>"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+ line="647"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="PxUsage"
+ message="Avoid using `"px"` as units; use `"dp"` instead"
+ errorLine1=" <dimen name="global_actions_top_padding">330px</dimen>"
+ errorLine2=" ~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+ line="1007"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="PxUsage"
+ message="Avoid using `"px"` as units; use `"dp"` instead"
+ errorLine1=" <dimen name="udfps_burn_in_offset_x">7px</dimen>"
+ errorLine2=" ~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+ line="1061"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="PxUsage"
+ message="Avoid using `"px"` as units; use `"dp"` instead"
+ errorLine1=" <dimen name="udfps_burn_in_offset_y">20px</dimen>"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+ line="1062"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="PxUsage"
+ message="Avoid using `"px"` as units; use `"dp"` instead"
+ errorLine1=" <dimen name="max_window_blur_radius">23px</dimen>"
+ errorLine2=" ~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+ line="1178"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="PxUsage"
+ message="Avoid using `"px"` as units; use `"dp"` instead"
+ errorLine1=" <dimen name="physical_power_button_center_screen_location_y">620px</dimen>"
+ errorLine2=" ~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+ line="1671"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="PxUsage"
+ message="Avoid using `"px"` as units; use `"dp"` instead"
+ errorLine1=" <dimen name="physical_fingerprint_sensor_center_screen_location_y">610px</dimen>"
+ errorLine2=" ~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/dimens.xml"
+ line="1684"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="SupportAnnotationUsage"
+ message="Did you mean `@get:VisibleForTesting`? Without `get:` this annotates the constructor parameter itself instead of the associated getter."
+ errorLine1=" @VisibleForTesting private val dialogProvider: DialogProvider"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt"
+ line="74"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="SupportAnnotationUsage"
+ message="This annotation does not apply for type String; expected int. Should `@com.android.systemui.shade.PanelState` be annotated with `@StringDef` instead?"
+ errorLine1="@PanelState"
+ errorLine2="~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/ShadeExpansionStateManager.kt"
+ line="162"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+ errorLine1=" Trace.beginSection("BiometricUnlockController#onBiometricDetected");"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java"
+ line="407"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+ errorLine1=" Trace.beginSection("BiometricUnlockController#onBiometricUnlocked");"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java"
+ line="418"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("$TAG#smallClock.animations.doze")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt"
+ line="525"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("$TAG#largeClock.animations.doze")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt"
+ line="528"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may throw an exception"
+ errorLine1=" Trace.traceBegin(Trace.TRACE_TAG_APP,"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingController.java"
+ line="128"
+ column="23"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+ errorLine1=" Trace.traceBegin("
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java"
+ line="179"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("DumpManager#dump()")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt"
+ line="100"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection(entry.name)"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt"
+ line="480"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("DumpsysTableLogger#printTableData")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/dump/DumpsysTableLogger.kt"
+ line="87"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+ errorLine1=" Trace.beginSection("ExpNotRow#onChildCountChanged (summary)");"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java"
+ line="2761"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+ errorLine1=" Trace.beginSection("HybridGroupManager#bindFromNotification");"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="102"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("ImageExporter_writeExif");"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ImageExporter.java"
+ line="436"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("WPMS.ImageWallpaper.CanvasEngine#loadWallpaper");"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java"
+ line="339"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("KeyguardBlueprintViewBinder#applyBlueprint")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt"
+ line="96"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("KeyguardBlueprintViewBinder#refreshTransition")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBlueprintViewBinder.kt"
+ line="143"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated");"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java"
+ line="955"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+ errorLine1=" Trace.beginSection("KeyGuardUpdateMonitor#handlerFaceAuthenticated");"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java"
+ line="1208"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+ errorLine1=" Trace.beginSection("KeyguardViewMediator#handleKeyguardDone");"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="2654"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+ errorLine1=" Trace.beginSection("KeyguardViewMediator#handleShow");"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="2780"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+ errorLine1=" Trace.beginSection("KeyguardViewMediator#handleStartKeyguardExitAnimation");"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="3011"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+ errorLine1=" Trace.traceBegin(Trace.TRACE_TAG_APP, "MediaControlPanel#bindPlayer<" + key + ">");"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java"
+ line="543"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+ errorLine1=" Trace.traceBegin(Trace.TRACE_TAG_APP,"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java"
+ line="1435"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("NSSLC#updateResources");"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java"
+ line="1331"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+ errorLine1=" Trace.traceBegin(Trace.TRACE_TAG_APP, "Pluggable<" + mName + ">.invalidateList");"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java"
+ line="55"
+ column="23"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+ errorLine1=" Trace.beginSection("KeyguardBouncer#show")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt"
+ line="184"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("KeyguardBouncer#hide")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt"
+ line="215"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+ errorLine1=" Trace.traceBegin(Trace.TRACE_TAG_APP, "QSTileViewImpl#onMeasure")"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt"
+ line="225"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("ResourceTrimmer#trimMemory")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/ResourceTrimmer.kt"
+ line="132"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may return early"
+ errorLine1=" Trace.beginSection("ScreenDecorations#onConfigurationChanged");"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java"
+ line="1071"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("ScreenOnCoordinator#onScreenTurningOn")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt"
+ line="57"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+ errorLine1=" Trace.traceBegin("
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java"
+ line="380"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+ errorLine1=" Trace.traceBegin("
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java"
+ line="406"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+ errorLine1=" Trace.traceBegin("
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java"
+ line="429"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+ errorLine1=" Trace.traceBegin("
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java"
+ line="440"
+ column="19"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may return early"
+ errorLine1=" Trace.traceBegin("
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java"
+ line="454"
+ column="23"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("TableLogBuffer#logChange(string)")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt"
+ line="199"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("TableLogBuffer#logChange(boolean)")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt"
+ line="213"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("TableLogBuffer#logChange(int)")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt"
+ line="227"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("TableLogBuffer#saveEvictedValue")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt"
+ line="264"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("UdfpsDisplayMode.enable")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDisplayMode.kt"
+ line="54"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `beginSection()` call is not always closed with a matching `endSection()` because the code in between may throw an exception"
+ errorLine1=" Trace.beginSection("UdfpsDisplayMode.disable")"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDisplayMode.kt"
+ line="83"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may throw an exception"
+ errorLine1=" Trace.traceBegin("
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt"
+ line="131"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="UnclosedTrace"
+ message="The `traceBegin()` call is not always closed with a matching `traceEnd()` because the code in between may throw an exception"
+ errorLine1=" Trace.traceBegin("
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt"
+ line="148"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="StringFormatInvalid"
+ message="Format string '`high_temp_alarm_notify_message`' is not a valid format string so it should not be passed to `String.format`"
+ errorLine1=" d.setMessage(mContext.getString(R.string.high_temp_alarm_notify_message, ""));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+ line="554"
+ column="22"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="2344"
+ column="5"
+ message="This definition does not require arguments"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-af/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bn/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-cs/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-da/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gl/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ja/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lv/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ru/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sv/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ur/strings.xml"
+ line="258"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `notification_group_overflow_indicator`: conversion is `s`, received `int` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" R.string.notification_group_overflow_indicator, number);"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java"
+ line="151"
+ column="65"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="620"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-af/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ar/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-as/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-az/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-be/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bn/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bs/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ca/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-cs/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-da/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-de/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-el/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings.xml"
+ line="1131"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-et/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-eu/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fa/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fi/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gl/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gu/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hi/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hu/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hy/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-in/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-is/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-it/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-iw/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ja/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ka/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kk/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-km/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kn/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ky/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lo/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lv/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mk/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ml/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mn/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mr/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-my/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ne/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nl/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-or/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pa/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pl/strings.xml"
+ line="1131"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ru/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-si/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sk/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sq/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sv/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ta/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-te/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tl/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tr/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uk/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ur/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uz/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-vi/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu/strings.xml"
+ line="1136"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="StringFormatMatches"
+ message="Suspicious argument type for formatting argument #1 in `days_timestamp`: conversion is `s`, received `long` (argument #2 in method call) (Did you mean formatting character `d`, 'o' or `x`?)"
+ errorLine1=" durationSinceLastInteraction.toDays());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java"
+ line="1315"
+ column="21"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="2997"
+ column="5"
+ message="Conflicting argument declaration here"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""theyre" is a common misspelling; did you mean "they're"?"
+ errorLine1=" <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"To set up Fingerprint Unlock again, your current fingerprint images and models will be deleted.\n\nAfter theyre deleted, youll need to set up Fingerprint Unlock again to use your fingerprint to unlock your phone or verify its you."</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="195"
+ column="191"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""theyre" is a common misspelling; did you mean "they're"?"
+ errorLine1=" <string name="fingerprint_re_enroll_dialog_content" msgid="4866561176695984879">"To set up Fingerprint Unlock again, your current fingerprint images and models will be deleted.\n\nAfter theyre deleted, youll need to set up Fingerprint Unlock again to use your fingerprint to unlock your phone or verify its you."</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings.xml"
+ line="195"
+ column="318"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""theyre" is a common misspelling; did you mean "they're"?"
+ errorLine1=" <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"To set up Fingerprint Unlock again, your current fingerprint images and model will be deleted.\n\nAfter theyre deleted, youll need to set up Fingerprint Unlock again to use your fingerprint to unlock your phone or verify its you."</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="196"
+ column="199"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""theyre" is a common misspelling; did you mean "they're"?"
+ errorLine1=" <string name="fingerprint_re_enroll_dialog_content_singular" msgid="3083663339787381218">"To set up Fingerprint Unlock again, your current fingerprint images and model will be deleted.\n\nAfter theyre deleted, youll need to set up Fingerprint Unlock again to use your fingerprint to unlock your phone or verify its you."</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings.xml"
+ line="196"
+ column="325"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""internett" is usually capitalized as "Internett""
+ errorLine1=" <string name="quick_settings_disclosure_management_named_vpn" msgid="4137564460025113168">"Denne enheten tilhører organisasjonen din og er koblet til internett via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+ line="520"
+ column="155"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""internett" is usually capitalized as "Internett""
+ errorLine1=" <string name="quick_settings_disclosure_named_management_named_vpn" msgid="2169227918166358741">"Denne enheten tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> og er koblet til internett via <xliff:g id="VPN_APP">%2$s</xliff:g>"</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+ line="521"
+ column="175"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""internett" is usually capitalized as "Internett""
+ errorLine1=" <string name="quick_settings_disclosure_management_vpns" msgid="929181757984262902">"Denne enheten tilhører organisasjonen din og er koblet til internett via VPN-er"</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+ line="524"
+ column="149"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""internett" is usually capitalized as "Internett""
+ errorLine1=" <string name="quick_settings_disclosure_named_management_vpns" msgid="3312645578322079185">"Denne enheten tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> og er koblet til internett via VPN-er"</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+ line="525"
+ column="170"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""internett" is usually capitalized as "Internett""
+ errorLine1=" <string name="quick_settings_disclosure_vpns" msgid="3586175303518266301">"Denne enheten er koblet til internett via VPN-er"</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+ line="530"
+ column="108"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""internett" is usually capitalized as "Internett""
+ errorLine1=" <string name="quick_settings_disclosure_managed_profile_named_vpn" msgid="153393105176944100">"Jobbappene dine er koblet til internett via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+ line="531"
+ column="130"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""internett" is usually capitalized as "Internett""
+ errorLine1=" <string name="quick_settings_disclosure_personal_profile_named_vpn" msgid="451254750289172191">"De personlige appene dine er koblet til internett via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+ line="532"
+ column="141"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""internett" is usually capitalized as "Internett""
+ errorLine1=" <string name="quick_settings_disclosure_named_vpn" msgid="6191822916936028208">"Denne enheten er koblet til internett via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+ line="533"
+ column="113"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""internett" is usually capitalized as "Internett""
+ errorLine1=" <string name="monitoring_description_named_vpn" msgid="8220190039787149671">"Denne enheten er koblet til internett via <xliff:g id="VPN_APP">%1$s</xliff:g>. Nettverksaktiviteten din, inkludert e-poster og nettlesingsdata, er synlig for VPN-leverandøren."</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+ line="549"
+ column="110"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""internett" is usually capitalized as "Internett""
+ errorLine1=" <string name="monitoring_description_managed_device_named_vpn" msgid="7693648349547785255">"Denne enheten er koblet til internett via <xliff:g id="VPN_APP">%1$s</xliff:g>. Nettverksaktiviteten din, inkludert e-poster og nettlesingsdata, er synlig for IT-administratoren din."</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+ line="550"
+ column="125"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""internett" is usually capitalized as "Internett""
+ errorLine1=" <string name="monitoring_description_two_named_vpns" msgid="6726394451199620634">"Denne enheten er koblet til internett via <xliff:g id="VPN_APP_0">%1$s</xliff:g> og <xliff:g id="VPN_APP_1">%2$s</xliff:g>. Nettverksaktiviteten din, inkludert e-poster og nettlesingsdata, er synlig for IT-administratoren din."</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+ line="551"
+ column="115"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""internett" is usually capitalized as "Internett""
+ errorLine1=" <string name="monitoring_description_managed_profile_named_vpn" msgid="7254359257263069766">"Jobbappene dine er koblet til internett via <xliff:g id="VPN_APP">%1$s</xliff:g>. Nettverksaktiviteten din i jobbapper, inkludert e-poster og nettlesingsdata, er synlige for IT-administratoren og VPN-leverandøren din."</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+ line="552"
+ column="128"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""internett" is usually capitalized as "Internett""
+ errorLine1=" <string name="monitoring_description_personal_profile_named_vpn" msgid="5083909710727365452">"De personlige appene dine er koblet til internett via <xliff:g id="VPN_APP">%1$s</xliff:g>. Nettverksaktiviteten din, inkludert e-poster og nettlesingsdata, er synlig for VPN-leverandøren din."</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+ line="553"
+ column="139"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message="Did you mean "Pos!" instead of "Pos1"?"
+ errorLine1=" <string name="keyboard_key_home" msgid="3734400625170020657">"Pos1"</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-de/strings.xml"
+ line="718"
+ column="67"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message="Did you mean "Pos!" instead of "Pos1"?"
+ errorLine1=" <string name="keyboard_key_move_home" msgid="3496502501803911971">"Pos1"</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-de/strings.xml"
+ line="738"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="Typos"
+ message=""internett" is usually capitalized as "Internett""
+ errorLine1=" <string name="mobile_data_disable_message" msgid="8604966027899770415">"Du får ikke tilgang til data eller internett via <xliff:g id="CARRIER">%s</xliff:g>. Internett er bare tilgjengelig via Wifi."</string>"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings.xml"
+ line="925"
+ column="112"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""pip_settings_bounds" is translated here but not found in default locale"
+ errorLine1=" <string translatable="false" name="pip_settings_bounds">"778 756 1258 1026"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ldrtl/config.xml"
+ line="20"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding">Drag left to quickly switch apps</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ldrtl/strings.xml"
+ line="21"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Sleep links om programme vinnig te wissel"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-af-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"መተግበሪያዎችን በፍጥነት ለመቀየር ወደ ግራ ይጎትቱ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"اسحب لليمين للتبديل السريع بين التطبيقات."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ar-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"তাত্ক্ষণিকভাৱে আনটো এপ্ ব্যৱহাৰ কৰিবলৈ বাওঁফালে টানক"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-as-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Digər tətbiqə sürətlə keçmək üçün sola çəkin"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-az-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Prevucite ulevo da biste brzo promenili aplikacije"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Каб хутка пераключыцца паміж праграмамі, перацягніце ўлева"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-be-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Плъзнете наляво за бързо превключване между приложенията"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"একটি অ্যাপ ছেড়ে দ্রুত অন্য অ্যাপে যেতে বাঁ দিকে টেনে আনুন"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bn-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Prevucite ulijevo za brzo prebacivanje između aplikacija"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bs-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Arrossega el dit cap a l\'esquerra per canviar ràpidament d\'aplicació"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ca-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Přetažením doleva rychle přepnete aplikace"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-cs-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Træk til venstre for hurtigt at skifte app"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-da-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Zum schnellen Wechseln der Apps nach links ziehen"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-de-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Σύρετε αριστερά για γρήγορη εναλλαγή εφαρμογών"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-el-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Drag left to quickly switch apps"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Drag left to quickly switch apps"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Drag left to quickly switch apps"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Drag left to quickly switch apps"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Drag left to quickly switch apps"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rXC-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Arrastra el dedo hacia la izquierda para cambiar de aplicación rápidamente"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Arrastra a la izquierda para cambiar de app rápidamente"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-rUS-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Rakenduste kiiresti vahetamiseks lohistage vasakule"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-et-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Arrastatu ezkerrera aplikazioa azkar aldatzeko"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-eu-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"برای سریع جابهجا شدن میان برنامهها، به چپ بکشید"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fa-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Vaihda sovellusta nopeasti vetämällä vasemmalle"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fi-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Déplacer vers la gauche pour changer rapidement d\'application"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Balayez l\'écran vers la gauche pour changer rapidement d\'application"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr-rCA-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Para cambiar de aplicación, arrastra o dedo rapidamente á esquerda"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gl-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"ઍપને ઝડપથી સ્વિચ કરવા માટે ડાબે ખેંચો"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gu-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"ऐप्लिकेशन को तेज़ी से बदलने के लिए उसे बाईं ओर खींचें और छोड़ें"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hi-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Povucite ulijevo da biste brzo promijenili aplikaciju"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Húzza balra az ujját az alkalmazások közötti gyors váltáshoz"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hu-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Քաշեք ձախ՝ հավելվածների միջև անցնելու համար"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hy-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Tarik ke kiri untuk beralih ke aplikasi dengan cepat"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-in-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Dragðu til vinstri til að skipta hratt á milli forrita"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-is-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Trascina verso sinistra per cambiare velocemente app"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-it-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"יש לגרור שמאלה כדי לעבור במהירות בין אפליקציות"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-iw-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"左にドラッグするとアプリを素早く切り替えることができます"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ja-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"აპების სწრაფად გადასართავად ჩავლებით გადაიტანეთ მარცხნივ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ka-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Қолданбалар арасында жылдам ауысу үшін солға қарай сүйреңіз"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kk-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"អូសទៅឆ្វេង ដើម្បីប្ដូរកម្មវិធីបានរហ័ស"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-km-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಬದಲಿಸಲು ತ್ವರಿತವಾಗಿ ಎಡಕ್ಕೆ ಡ್ರ್ಯಾಗ್ ಮಾಡಿ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kn-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"앱을 빠르게 전환하려면 왼쪽으로 드래그"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Колдонмолорду тез которуштуруу үчүн, солго сүйрөңүз"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ky-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"ລາກໄປຊ້າຍເພື່ອສະຫຼັບແອັບຢ່າງວ່ອງໄວ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lo-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Vilkite į kairę, kad greitai perjungtumėte programas"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Lai ātri pārslēgtu lietotnes, velciet pa kreisi"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lv-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Повлечете налево за брзо префрлање меѓу апликациите"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mk-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"ആപ്പുകൾ പെട്ടെന്ന് മാറ്റാൻ ഇടത്തോട്ട് വലിച്ചിടുക"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ml-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Аппыг хурдан сэлгэхийн тулд зүүн тийш чирэх"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mn-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"अॅप्स त्वरित स्विच करण्यासाठी डावीकडे ड्रॅग करा"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mr-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Seret ke kiri untuk beralih apl dengan pantas"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ms-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"အက်ပ်များ အမြန်ပြောင်းရန် ဘယ်ဘက်သို့ ဖိဆွဲပါ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-my-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Dra til venstre for å bytte app raskt"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"एपहरू द्रुत गतिमा बदल्न बायाँतिर ड्र्याग गर्नुहोस्"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ne-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Sleep naar links om snel tussen apps te schakelen"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nl-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"ଆପ୍ ମଧ୍ୟରେ ଶୀଘ୍ର ବଦଳ କରିବା ପାଇଁ ବାମକୁ ଡ୍ରାଗ୍ କରନ୍ତୁ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-or-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"ਐਪਾਂ ਵਿਚਾਲੇ ਤੇਜ਼ੀ ਨਾਲ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਖੱਬੇ ਪਾਸੇ ਵੱਲ ਘਸੀਟੋ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pa-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Przeciągnij w lewo, by szybko przełączyć aplikacje"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pl-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Arraste para a esquerda para mudar rapidamente de app"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Arraste para a esquerda para mudar rapidamente de app"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rBR-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Arrastar para a esquerda para mudar rapidamente de app"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Trage spre stânga pentru a comuta rapid între aplicații"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Перетащите влево, чтобы быстро переключиться между приложениями"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ru-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"ඉක්මනින් යෙදුම් මාරු කිරීමට වමට අදින්න"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-si-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Presunutím doľava rýchlo prepnete aplikácie"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sk-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Povlecite v levo za hiter preklop med aplikacijami"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Zvarrit majtas për të ndërruar aplikacionet me shpejtësi"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sq-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Превуците улево да бисте брзо променили апликације"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Tryck och dra åt vänster för att snabbt byta mellan appar"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sv-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Buruta kushoto ili ubadili kati ya programu haraka"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"ஆப்ஸை வேகமாக மாற்ற, இடப்புறம் இழுக்கவும்"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ta-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"యాప్లను శీఘ్రంగా స్విచ్ చేయడానికి ఎడమ వైపునకు లాగండి"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-te-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"ลากไปทางซ้ายเพื่อสลับแอปอย่างรวดเร็ว"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"I-drag pakaliwa para mabilisang magpalipat-lipat ng app."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tl-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Uygulamaları hızlıca değiştirmek için sola sürükleyin"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tr-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Потягніть уліво, щоб швидко переходити між додатками"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uk-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"تیزی سے ایپس کو سوئچ کرنے کے لیے بائيں طرف گھسیٹیں"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ur-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Ilovalarni tezkor almashtirish uchun chapga torting"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uz-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Kéo sang trái để chuyển nhanh giữa các ứng dụng"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-vi-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"向左拖动可快速切换应用"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rCN-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"向左拖曳即可快速切換應用程式"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rHK-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"向左拖曳即可快速切換應用程式"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rTW-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""recents_quick_scrub_onboarding" is translated here but not found in default locale"
+ errorLine1=" <string name="recents_quick_scrub_onboarding" msgid="2452671841151577157">"Hudulela ngakwesokunxele ukuze ushintshe ngokushesha izinhlelo zokusebenza"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu-ldrtl/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Vee alles uit"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-af-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"ሁሉንም አጥራ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"محو الكل"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ar-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Выдаліць усё"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-be-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Изчистване"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Esborra-ho"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ca-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Smazat vše"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-cs-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Ryd alt"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-da-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Löschen"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-de-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Εκκαθ. όλων"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-el-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Clear all"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Borrar todo"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Eliminar todas"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-rUS-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Kust. kõik"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-et-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"پاک کردن همه موارد"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fa-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Tyhjennä kaikki"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fi-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Tout effacer"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"सभी साफ़ करें"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hi-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Obriši sve"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Össz.törl."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hu-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Hapus semua"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-in-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Cancella"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-it-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"נקה הכל"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-iw-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"すべて消去"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ja-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"모두 지우기"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Išv. viską"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Notīr.visu"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lv-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Ksgkn smua"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ms-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Tøm alle"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Alles wissen"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nl-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Wyczyść"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pl-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Limpar tudo"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Limpar td"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Şterg. tot"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Очистить все"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ru-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Vymazať všetko"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sk-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Izbriši vse"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Обриши све"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Rensa alla"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sv-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Futa zote"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"ล้างทั้งหมด"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"I-clear"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tl-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Tümü temzl"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tr-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Очист. все"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uk-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Xóa tất cả"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-vi-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"全部清除"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rCN-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"全部清除"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rTW-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""status_bar_clear_all_button" is translated here but not found in default locale"
+ errorLine1=" <string name="status_bar_clear_all_button" msgid="4661583896803349732">"Sula konke"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu-large/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Skerm is nou in landskapsoriëntering gesluit."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-af-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"አሁን ማያበወርድ ገፅ አቀማመጥ ተሸንጉሯል።"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"تم قفل الشاشة الآن في الاتجاه الأفقي"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ar-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"تم قفل الشاشة الآن في الاتجاه العمودي."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ar-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"স্ক্ৰীনখন এতিয়া লেণ্ডস্কে\'প স্ক্ৰীনৰ দিশত লক কৰা অৱস্থাত আছে"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-as-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Hazırda ekran landşaft orientasiyasında kilidlənib."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-az-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Ekran je sada zaključan u vertikalnom položaju."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Цяпер экран заблакаваны ў альбомнай арыентацыі."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-be-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Екранът е заключен в хоризонтална ориентация."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"Екранът е заключен във вертикална ориентация."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"এখন ল্যান্ডস্কেপ সজ্জাতে স্ক্রিন লক করা হয়েছে৷"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bn-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Ekran je sada zaključan u vodoravnom prikazu."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bs-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Ara la pantalla està bloquejada en orientació horitzontal."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ca-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"Ara la pantalla està bloquejada en orientació vertical."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ca-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Obrazovka je teď uzamčena v orientaci na šířku."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-cs-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Skærmen er nu låst i liggende retning."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-da-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Bildschirm bleibt jetzt im Querformat."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-de-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Ο προσανατολισμός της οθόνης κλειδώθηκε σε οριζόντια προβολή."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-el-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Screen is now locked in landscape orientation."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Screen is now locked in landscape orientation."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Screen is now locked in landscape orientation."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"Screen is now locked in portrait orientation."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Screen is now locked in landscape orientation."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Screen is now locked in landscape orientation."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rXC-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"La pantalla está ahora bloqueada en orientación horizontal."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"La pantalla está bloqueada en orientación paisaje."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-rUS-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Ekraan on nüüd lukustatud horisontaalasendisse."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-et-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Pantaila horizontalki blokeatuta dago."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-eu-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"صفحه اکنون در حالت افقی قفل است."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fa-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"صفحه اکنون در جهت عمودی قفل است."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fa-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Ruutu on nyt lukittu vaakasuuntaan."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fi-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"Ruutu on nyt lukittu pystysuuntaan."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fi-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"L\'écran est désormais verrouillé en orientation paysage."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"L\'écran est désormais verrouillé au format paysage."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr-rCA-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Agora a pantalla está bloqueada en orientación horizontal."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gl-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"સ્ક્રીન હવે લેન્ડસ્કેપ ઓરિએન્ટેશનમાં લૉક કરેલ છે."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gu-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"स्क्रीन अभी लैंडस्केप दिशा में लॉक है."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hi-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Zaslona je sada zaključan u pejzažnoj orijentaciji."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"Zaslona je sada zaključan u portretnoj orijentaciji."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"A képernyő zárolva van fekvő tájolásban."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hu-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"A képernyő zárolva van álló tájolásban."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hu-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Էկրանն այժմ կողպված է հորիզոնական դիրքավորման մեջ:"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hy-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Sekarang layar dikunci dalam orientasi lanskap."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-in-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"Sekarang layar dikunci dalam orientasi potret."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-in-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Skjárinn er nú læstur á langsniði."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-is-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Lo schermo è bloccato in orientamento orizzontale."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-it-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"המסך נעול כעת לרוחב."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-iw-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"המסך נעול כעת לאורך"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-iw-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"画面を横向きにロックしました。"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ja-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"ეკრანი ამჟამად დაბლოკილია თარაზულ ორიენტაციაში"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ka-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Экран қазір ландшафт бағытына бекітілген."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kk-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"ឥឡូវអេក្រង់ជាប់សោក្នុងទិសផ្ដេក។"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-km-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"ಪರದೆಯು ಇದೀಗ ಲ್ಯಾಂಡ್ಸ್ಕೇಪ್ ಒರಿಯಂಟೇಶನ್ನಲ್ಲಿ ಲಾಕ್ ಆಗಿದೆ."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kn-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"화면이 현재 가로 방향으로 잠겨 있습니다."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Экран азыр туурасынан кулпуланган."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ky-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked">Screen is now locked in landscape orientation.</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"ໜ້າຈໍຕອນນີ້ຖືກລັອກໄວ້ໃນແບບລວງນອນ."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lo-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Dabar ekranas užrakintas horizontalioje pozicijoje."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"Dabar ekranas užrakintas vertikalioje pozicijoje."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Ekrāns tagad ir bloķēts ainavas orientācijā."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lv-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"Ekrāns tagad ir bloķēts portreta orientācijā."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lv-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Сега екранот е заклучен во ориентација на пејзаж."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mk-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"ലാൻഡ്സ്കേപ്പ് ഓറിയന്റേഷനിൽ സ്ക്രീൻ ലോക്കുചെയ്തു."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ml-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Дэлгэц хэвтээ чиглэлд түгжигдсэн."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mn-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"स्क्रीन आता लॅंडस्केप ओरिएंटेशनमध्ये लॉक केली आहे."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mr-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Skrin kini dikunci dalam orientasi landskap."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ms-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"ဖန်သားပြင် အနေအထားက အလျားလိုက်အဖြစ် ပုံသေ လုပ်ထားပါသည်။"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-my-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Skjermen er nå låst i liggende retning."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"स्क्रिन अहिले ल्यान्डस्केप अवस्थामा बन्द छ।"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ne-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Het scherm is nu vergrendeld in liggende stand."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nl-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"ଲ୍ୟାଣ୍ଡସ୍କେପ୍ ଅବସ୍ଥାରେ ବର୍ତ୍ତମାନ ସ୍କ୍ରୀନ୍ଟି ଲକ୍ ଅଛି।"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-or-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"ਸਕ੍ਰੀਨ ਹੁਣ ਲੈਂਡਸਕੇਪ ਅਨੁਕੂਲਨ ਵਿੱਚ ਲਾਕ ਕੀਤੀ ਗਈ ਹੈ।"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pa-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Ekran jest teraz zablokowany w orientacji poziomej"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pl-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"A tela está bloqueada na orientação cenário."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"A tela está bloqueada na orientação cenário."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rBR-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"O ecrã está agora bloqueado na orientação horizontal."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Ecranul este acum blocat în orientarea de tip peisaj."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"Ecranul este acum blocat în orientarea de tip portret."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Выбрана только альбомная ориентация экрана."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ru-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"තිරය දැන් තිරස් දිශානතිය අගුළු දමා ඇත."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-si-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Obrazovka je teraz uzamknutá v orientácii na šírku."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sk-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"Obrazovka je teraz uzamknutá v orientácii na výšku."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sk-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Zaslon je zaklenjen v ležeči usmerjenosti."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"Zaslon je zaklenjen v pokončni usmerjenosti."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Ekrani është kyçur tani në orientimin horizontal."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sq-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Екран је сада закључан у вертикалном положају."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"Екран је сада закључан у хоризонталном положају."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Bildskärmens riktning är nu låst i liggande format."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sv-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Skrini imefungwa sasa katika uelekezo wa mandhari."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"தற்போது திரை நிலைபரப்பு திசையமைப்பில் பூட்டப்பட்டுள்ளது."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ta-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"స్క్రీన్ ఇప్పుడు ల్యాండ్స్కేప్ దృగ్విన్యాసంలో లాక్ చేయబడింది."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-te-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"ขณะนี้หน้าจอถูกล็อกในแนวนอน"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"ขณะนี้หน้าจอถูกล็อกการวางแนวในแนวตั้ง"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Naka-lock na ngayon ang screen at nasa pahigang oryentasyon."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tl-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"Naka-lock na ngayon ang screen at nasa patayong orientation."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tl-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Ekran şimdi yatay yönde kilitlendi."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tr-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Екран зараз заблоковано в альбомній орієнтації."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uk-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"Екран зараз заблоковано в книжковій орієнтації."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uk-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"اسکرین اب لینڈ اسکیپ سمت بندی میں مقفل ہے۔"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ur-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Ekran hozir albom joylashuvi bo‘yicha qulflanadi"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uz-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Màn hình hiện bị khóa theo hướng ngang."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-vi-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="1716565836190665743">"Màn hình hiện bị khóa theo hướng dọc."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-vi-port/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"屏幕已锁定为横向浏览模式。"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rCN-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"螢幕現已鎖定為橫向模式"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rHK-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"螢幕現已鎖定為橫向模式"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rTW-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""toast_rotation_locked" is translated here but not found in default locale"
+ errorLine1=" <string name="toast_rotation_locked" msgid="4914046305911646988">"Isikrini okwamanje sivaliwe ekujikelezeni okumile."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu-land/strings.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Kennisgewings af"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-af-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"ማሳወቂያዎች ጠፍተዋል"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"إيقاف التنبيهات"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ar-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Паведамленні адключаныя"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-be-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Известията са изключени"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Notificacions desactivades"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ca-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Oznámení jsou vypnuta"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-cs-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Meddelelser: fra"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-da-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Benachrichtigungen aus"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-de-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Ειδοποιήσεις ανενεργές"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-el-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Notifications off"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Notificaciones desactivadas"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Notificaciones desactivadas"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-rUS-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Teatised väljas"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-et-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"اعلان ها خاموش"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fa-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Ilmoitukset pois käytöstä"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fi-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Notifications désactivées"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"सूचनाएं बंद"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hi-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Obavijesti isključene"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Értesítések kikapcsolva"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hu-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Pemberitahuan mati"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-in-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Notifiche disattivate"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-it-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"מצב התראות כבוי"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-iw-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"通知OFF"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ja-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"알림 사용 안함"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Pranešimai išjungti"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Paziņojumi ir izslēgti."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lv-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Pemberitahuan dimatikan"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ms-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Varslinger er deaktivert"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Meldingen uit"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nl-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Powiadomienia wyłączone"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pl-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Notificações desativadas"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Notificações desativadas"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Notificările sunt dezactivate"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Уведомления отключены"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ru-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Upozornenia sú vypnuté"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sk-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Obvestila so izklopljena"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Обавештења су искључена"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Meddelanden inaktiverade"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sv-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Arifa imezimwa"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"การแจ้งเตือนปิดอยู่"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Naka-off ang mga notification"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tl-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Bildirimler kapalı"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tr-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Сповіщення вимкнено"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uk-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Tắt thông báo"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-vi-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"通知功能已停用"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rCN-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"關閉通知"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rTW-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_title" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_title" msgid="1860117696034775851">"Izaziso zivaliwe"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu-large/strings.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Tik hier om kennisgewings weer aan te skakel."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-af-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"ማሳወቂያን መልሶ ለማብራ እዚህ ሁለቴ ንካ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"انقر هنا لإعادة تشغيل التنبيهات."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ar-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Націсніце тут, каб зноў уключыць апавяшчэнні."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-be-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Докоснете тук, за да включите отново известията."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Pica aquí per tornar a activar les notificacions."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ca-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Chcete-li oznámení znovu zapnout, klepněte sem."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-cs-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Tryk her for at slå meddelelser til igen."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-da-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Tippen Sie hier, um die Benachrichtigungen wieder zu aktivieren."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-de-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Πατήστε εδώ για να ενεργοποιήσετε ξανά τις ειδοποιήσεις."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-el-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Tap here to turn notifications back on."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Toca aquí para volver a activar las notificaciones."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Toca aquí para volver a activar las notificaciones."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-rUS-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Teatiste uuesti sisselülitamiseks koputage siia."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-et-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"برای روشن کردن مجدد اعلان ها، اینجا را ضربه بزنید."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fa-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Ota ilmoitukset uudelleen käyttöön napauttamalla tätä."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fi-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Appuyez ici pour réactiver les notifications."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"सूचनाओं को पुन: चालू करने के लिए यहां टैप करें."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hi-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Dotaknite ovdje da biste ponovo uključili obavijesti."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Itt érintse meg az értesítések bekapcsolásához."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hu-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Ketuk di sini untuk menghidupkan pemberitahuan lagi."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-in-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Tocca qui per riattivare le notifiche."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-it-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"הקש כאן כדי להפעיל מחדש את ההתראות."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-iw-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"通知を再度ONにするにはここをタップします。"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ja-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"알림을 다시 사용하려면 여기를 터치하세요."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Jei norite įjungti pranešimus, palieskite čia."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Pieskarieties šeit, lai atkal ieslēgtu paziņojumus."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lv-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Ketik di sini untuk menghidupkan kembali pemberitahuan."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ms-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Trykk her for å aktivere varslinger på nytt."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Tik hier om meldingen weer in te schakelen."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nl-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Dotknij tutaj, aby z powrotem włączyć powiadomienia."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pl-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Toque aqui para ativar as notificações novamente."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Toque aqui para voltar a ativar as notificações."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Apăsaţi aici pentru a reactiva notificările."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Нажмите здесь, чтобы снова включить уведомления."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ru-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Klepnutím sem upozornenia znova povolíte."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sk-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Tapnite tukaj, da spet vklopite obvestila."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Додирните овде да бисте поново укључили обавештења."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Knacka lätt här om du vill aktivera meddelanden igen."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sv-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Gonga hapa ili kuwasha tena arifa."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"แตะที่นี่เพื่อเปิดการแจ้งเตือนอีกครั้ง"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Mag-tap dito upang i-on muli ang mga notification."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tl-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Bildirimleri tekrar açmak için buraya hafifçe vurun."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tr-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Торкніться тут, щоб знову ввімкнути сповіщення."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uk-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Chạm vào đây để bật lại thông báo."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-vi-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"点按此处可重新启用通知功能。"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rCN-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"輕按這裡即可重新開啟通知。"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rTW-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""notifications_off_text" is translated here but not found in default locale"
+ errorLine1=" <string name="notifications_off_text" msgid="1439152806320786912">"Thepha lana ukuvula futhi izaziso."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu-large/strings.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Gas"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-af/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"እንግዳ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"ضيف"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ar/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"অতিথি"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-as/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Qonaq"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-az/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Gost"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Госць"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-be/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Гост"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"অতিথি"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bn/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Gost"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bs/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Convidat"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ca/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Host"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-cs/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Gæst"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-da/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Gast"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-de/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Επισκέπτης"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-el/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Guest"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Guest"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Guest"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Guest"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Guest"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Invitado"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-rUS/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Invitado"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Külaline"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-et/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Gonbidatua"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-eu/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"مهمان"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fa/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Vieras"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fi/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Invité"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr-rCA/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Invité"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Convidado"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gl/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"અતિથિ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gu/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"मेहमान"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hi/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Gost"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Vendég"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hu/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Հյուր"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hy/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Tamu"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-in/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Gestur"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-is/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Ospite"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-it/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"אורח"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-iw/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"ゲスト"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ja/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"სტუმარი"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ka/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Қонақ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kk/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"ភ្ញៀវ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-km/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"ಅತಿಥಿ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kn/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"게스트"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Конок"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ky/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"ແຂກ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lo/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Svečias"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Viesis"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lv/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Гостин"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mk/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"അതിഥി"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ml/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Зочин"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mn/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"अतिथी"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mr/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Tetamu"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ms/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"ဧည့်သည်"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-my/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Gjest"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"अतिथि"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ne/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Gast"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nl/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"ଅତିଥି"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-or/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"ਮਹਿਮਾਨ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pa/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Gość"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pl/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Visitante"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Convidado"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Visitante"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Invitat"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Гость"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ru/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"අමුත්තා"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-si/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Hosť"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sk/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Gost"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"I ftuar"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sq/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Гост"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Gäst"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sv/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Mgeni"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"விருந்தினர்"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ta/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"అతిథి"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-te/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"ผู้มาเยือน"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Bisita"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tl/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Misafir"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tr/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Гість"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uk/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"مہمان"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ur/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Mehmon"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uz/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Khách"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-vi/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"访客"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"訪客"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rHK/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"訪客"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rTW/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_guest" is translated here but not found in default locale"
+ errorLine1=" <string name="car_guest" msgid="3738772168718508650">"Isivakashi"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu/strings_car.xml"
+ line="22"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Gas"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-af/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"እንግዳ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"ضيف"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ar/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"অতিথি"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-as/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Qonaq"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-az/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Gost"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Госць"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-be/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Гост"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"অতিথি"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bn/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Gost"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bs/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Convidat"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ca/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Host"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-cs/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Gæst"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-da/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Gast"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-de/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Επισκέπτης"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-el/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Guest"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Guest"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Guest"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Guest"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Guest"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Invitado"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-rUS/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Invitado"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Külaline"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-et/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Gonbidatua"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-eu/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"مهمان"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fa/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Vieras"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fi/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Invité"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr-rCA/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Invité"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Convidado"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gl/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"અતિથિ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gu/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"मेहमान मोड"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hi/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Gost"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Vendég"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hu/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Հյուր"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hy/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Tamu"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-in/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Gestur"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-is/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Ospite"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-it/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"אורח"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-iw/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"ゲスト"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ja/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"სტუმარი"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ka/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Қонақ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kk/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"ភ្ញៀវ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-km/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"ಅತಿಥಿ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kn/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"게스트"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Конок"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ky/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"ແຂກ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lo/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Svečias"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Viesis"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lv/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Гостин"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mk/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"അതിഥി"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ml/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Зочин"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mn/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"अतिथी"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mr/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Tetamu"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ms/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"ဧည့်သည်"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-my/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Gjest"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"अतिथि"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ne/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Gast"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nl/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"ଅତିଥି"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-or/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"ਮਹਿਮਾਨ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pa/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Gość"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pl/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Visitante"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Convidado"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Visitante"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Invitat"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Гость"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ru/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"අමුත්තා"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-si/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Hosť"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sk/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Gost"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"I ftuar"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sq/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Гост"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Gäst"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sv/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Mgeni"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"விருந்தினர்"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ta/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"అతిథి"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-te/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"ผู้มาเยือน"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Bisita"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tl/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Misafir"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tr/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Гість"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uk/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"مہمان"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ur/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Mehmon"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uz/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Khách"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-vi/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"访客"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"訪客"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rHK/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"訪客"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rTW/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""start_guest_session" is translated here but not found in default locale"
+ errorLine1=" <string name="start_guest_session" msgid="7055742120180595689">"Isivakashi"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu/strings_car.xml"
+ line="23"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Voeg gebruiker by"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-af/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"ተጠቃሚ አክል"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"إضافة المستخدم"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ar/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"ব্যৱহাৰকাৰী যোগ কৰক"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-as/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"İstifadəçi əlavə edin"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-az/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Dodaj korisnika"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Дадаць карыстальніка"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-be/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Добавяне на потребител"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"ব্যবহারকারীকে যুক্ত করুন"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bn/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Dodaj korisnika"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bs/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Afegeix un usuari"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ca/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Přidat uživatele"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-cs/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Tilføj bruger"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-da/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Nutzer hinzufügen"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-de/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Προσθήκη χρήστη"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-el/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Add User"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Add User"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Add User"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Add User"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Add User"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Agregar usuario"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-rUS/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Añadir usuario"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Kasutaja lisamine"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-et/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Gehitu erabiltzaile bat"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-eu/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"افزودن کاربر"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fa/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Lisää käyttäjä"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fi/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Ajouter un utilisateur"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr-rCA/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Ajouter un utilisateur"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Engadir usuario"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gl/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"વપરાશકર્તા ઉમેરો"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gu/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"उपयोगकर्ता जोड़ें"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hi/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Dodajte korisnika"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Felhasználó hozzáadása"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hu/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Ավելացնել օգտատեր"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hy/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Tambahkan Pengguna"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-in/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Bæta notanda við"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-is/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Aggiungi utente"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-it/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"הוספת משתמש"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-iw/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"ユーザーを追加"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ja/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"მომხმარებლის დამატება"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ka/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Пайдаланушыны енгізу"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kk/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"បញ្ចូលអ្នកប្រើប្រាស់"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-km/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"ಬಳಕೆದಾರ ಸೇರಿಸು"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kn/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"사용자 추가"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Колдонуучу кошуу"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ky/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"ເພີ່ມຜູ້ໃຊ້"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lo/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Pridėti naudotoją"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Lietotāja pievienošana"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lv/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Додај корисник"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mk/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"ഉപയോക്താവിനെ ചേര്ക്കുക"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ml/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Хэрэглэгч нэмэх"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mn/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"वापरकर्ता जोडा"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mr/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Tambah Pengguna"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ms/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"အသုံးပြုသူ ထည့်ရန်"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-my/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Legg til bruker"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"प्रयोगकर्ता थप्नुहोस्"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ne/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Gebruiker toevoegen"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nl/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"ୟୁଜର୍ଙ୍କୁ ଯୋଡ଼ନ୍ତୁ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-or/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰੋ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pa/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Dodaj użytkownika"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pl/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Adicionar usuário"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Adicionar utilizador"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Adicionar usuário"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Adăugați un utilizator"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Добавить пользователя"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ru/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"පරිශීලක එක් කරන්න"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-si/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Pridať používateľa"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sk/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Dodaj uporabnika"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Shto përdorues"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sq/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Додај корисника"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Lägg till användare"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sv/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Ongeza Mtumiaji"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"பயனரைச் சேர்க்கவும்"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ta/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"వినియోగదారును జోడించండి"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-te/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"เพิ่มผู้ใช้"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Magdagdag ng User"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tl/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Kullanıcı Ekle"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tr/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Додати користувача"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uk/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"صارف شامل کریں"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ur/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Foydalanuvchi qo‘shish"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uz/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Thêm người dùng"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-vi/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"添加用户"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"新增使用者"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rHK/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"新增使用者"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rTW/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_add_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_add_user" msgid="5245196248349230898">"Engeza umsebenzisi"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu/strings_car.xml"
+ line="24"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Nuwe gebruiker"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-af/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"አዲስ ተጠቃሚ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"مستخدم جديد"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ar/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"নতুন ব্যৱহাৰকাৰী"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-as/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Yeni İstifadəçi"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-az/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Novi korisnik"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Новы карыстальнік"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-be/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Нов потребител"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"নতুন ব্যবহারকারী"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bn/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Novi korisnik"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bs/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Usuari nou"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ca/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Nový uživatel"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-cs/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Ny bruger"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-da/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Neuer Nutzer"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-de/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Νέος χρήστης"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-el/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"New User"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"New User"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"New User"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"New User"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"New User"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Nuevo usuario"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-rUS/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Nuevo usuario"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Uus kasutaja"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-et/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Erabiltzaile berria"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-eu/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"کاربر جدید"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fa/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Uusi käyttäjä"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fi/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Nouvel utilisateur"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr-rCA/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Nouvel utilisateur"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Novo usuario"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gl/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"નવા વપરાશકર્તા"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gu/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"नया उपयोगकर्ता"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hi/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Novi korisnik"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Új felhasználó"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hu/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Նոր օգտատեր"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hy/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Pengguna Baru"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-in/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Nýr notandi"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-is/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Nuovo utente"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-it/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"משתמש חדש"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-iw/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"新しいユーザー"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ja/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"ახალი მომხმარებელი"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ka/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Жаңа пайдаланушы"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kk/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"អ្នកប្រើប្រាស់ថ្មី"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-km/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"ಹೊಸ ಬಳಕೆದಾರ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kn/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"신규 사용자"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Жаңы колдонуучу"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ky/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"ຜູ້ໃຊ້ໃໝ່"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lo/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Naujas naudotojas"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Jauns lietotājs"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lv/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Нов корисник"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mk/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"പുതിയ ഉപയോക്താവ്"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ml/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Шинэ хэрэглэгч"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mn/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"नवीन वापरकर्ता"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mr/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Pengguna Baharu"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ms/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"အသုံးပြုသူ အသစ်"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-my/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Ny bruker"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"नयाँ प्रयोगकर्ता"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ne/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Nieuwe gebruiker"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nl/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"ନୂଆ ୟୁଜର୍"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-or/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"ਨਵਾਂ ਵਰਤੋਂਕਾਰ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pa/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Nowy użytkownik"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pl/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Novo usuário"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Novo utilizador"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Novo usuário"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Utilizator nou"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Новый пользователь"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ru/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"නව පරිශීලක"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-si/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Nový používateľ"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sk/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Nov uporabnik"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Përdorues i ri"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sq/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Нови корисник"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Ny användare"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sv/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Mtumiaji Mpya"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"புதிய பயனர்"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ta/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"కొత్త వినియోగదారు"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-te/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"ผู้ใช้ใหม่"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Bagong User"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tl/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Yeni Kullanıcı"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tr/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Новий користувач"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uk/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"نیا صارف"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ur/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Yangi foydalanuvchi"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uz/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Người dùng mới"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-vi/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"新用户"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"新使用者"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rHK/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"新使用者"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rTW/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""car_new_user" is translated here but not found in default locale"
+ errorLine1=" <string name="car_new_user" msgid="8142927244990323906">"Umsebenzisi omusha"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu/strings_car.xml"
+ line="25"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Wanneer jy \'n nuwe gebruiker byvoeg, moet daardie persoon hul spasie opstel."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-af/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"አዲስ ተጠቃሚ ሲያክሉ ያ ሰው የራሳቸውን ቦታ ማቀናበር አለባቸው።"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"عند إضافة مستخدم جديد، عليه إعداد مساحته."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ar/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"আপুনি কোনো নতুন ব্য়ৱহাৰকাৰীক যোগ কৰিলে তেখেতে নিজৰ বাবে খালী ঠাই ছেট আপ কৰিব লাগে।"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-as/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Yeni istifadəçi əlavə etdiyinizdə həmin şəxs öz yerini təyin etməlidir."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-az/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kada dodate novog korisnika, ta osoba treba da podesi svoj prostor."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Калі вы дадаяце новага карыстальніка, яму трэба наладзіць свой профіль."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-be/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Когато добавите нов потребител, той трябва да настрои работното си пространство."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"আপনি কোনও নতুন ব্যবহারকারীকে যোগ করলে তাকে তার স্পেস সেট-আপ করে নিতে হবে।"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bn/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kada dodate novog korisnika, ta osoba treba postaviti svoj prostor."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bs/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Quan s\'afegeix un usuari nou, aquest usuari ha de configurar el seu espai."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ca/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Každý nově přidaný uživatel si musí nastavit vlastní prostor."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-cs/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Når du tilføjer en ny bruger, skal vedkommende konfigurere sit område."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-da/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Wenn du einen neuen Nutzer hinzufügst, muss dieser seinen Bereich einrichten."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-de/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Όταν προσθέτετε έναν νέο χρήστη, αυτός ο χρήστης θα πρέπει να ρυθμίσει τον χώρο του."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-el/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"When you add a new user, that person needs to set up their space."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"When you add a new user, that person needs to set up their space."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"When you add a new user, that person needs to set up their space."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"When you add a new user, that person needs to set up their space."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"When you add a new user, that person needs to set up their space."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Cuando agregues un usuario nuevo, esa persona deberá configurar su espacio."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-rUS/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Al añadir un nuevo usuario, este debe configurar su espacio."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kui lisate uue kasutaja, siis peab ta seadistama oma ruumi."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-et/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Erabiltzaile bat gehitzen duzunean, bere eremua konfiguratu beharko du."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-eu/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"وقتی کاربر جدیدی اضافه میکنید، آن فرد باید فضای خود را تنظیم کند."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fa/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kun lisäät uuden käyttäjän, hänen on määritettävä oman tilansa asetukset."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fi/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr-rCA/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Lorsque vous ajoutez un utilisateur, celui-ci doit configurer son espace."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Cando engadas un usuario novo, este deberá configurar o seu espazo."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gl/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"જ્યારે તમે કોઈ નવા વપરાશકર્તાને ઉમેરો છો, ત્યારે તે વ્યક્તિએ તેમની સ્પેસ સેટ કરવાની જરૂર રહે છે."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gu/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"जब आप कोई नया उपयोगकर्ता जोड़ते हैं तो, उस व्यक्ति को अपनी जगह सेट करनी होती है."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hi/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kada dodate novog korisnika, ta osoba mora postaviti vlastiti prostor."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Ha új felhasználót ad hozzá, az illetőnek be kell állítania saját felületét."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hu/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Երբ դուք նոր օգտատեր եք ավելացնում, նա պետք է կարգավորի իր պրոֆիլը:"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hy/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Saat Anda menambahkan pengguna baru, orang tersebut perlu menyiapkan ruangnya sendiri."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-in/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Þegar þú bætir nýjum notanda við þarf viðkomandi að setja upp sitt eigið svæði."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-is/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Il nuovo utente, una volta aggiunto, dovrà configurare il proprio spazio."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-it/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"בעת הוספת משתמש חדש, על משתמש זה להגדיר את המרחב שלו."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-iw/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"新しいユーザーを追加したら、そのユーザーは自分のスペースをセットアップする必要があります。"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ja/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"ახალი მომხმარებლის დამატებისას, ამ მომხმარებელს საკუთარი სივრცის შექმნა მოუწევს."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ka/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Енгізілген жаңа пайдаланушы өз профилін реттеуі керек."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kk/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"នៅពេលដែលអ្នកបញ្ចូលអ្នកប្រើប្រាស់ថ្មី បុគ្គលនោះត្រូវតែរៀបចំទំហំផ្ទុករបស់គេ។"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-km/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"ನೀವು ಹೊಸ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿದಾಗ, ಆ ವ್ಯಕ್ತಿಯು ಅವರ ಸ್ಥಳವನ್ನು ಸೆಟಪ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kn/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"추가된 새로운 사용자는 자신의 공간을 설정해야 합니다."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Жаңы колдонуучу кошулганда, ал өзүнүн профилин жөндөп алышы керек."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ky/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"ເມື່ອທ່ານເພີ່ມຜູ້ໃຊ້ໃໝ່, ບຸກຄົນນັ້ນຈຳເປັນຕ້ອງຕັ້ງຄ່າພື້ນທີ່ຂອງເຂົາເຈົ້າ."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lo/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kai pridedate naują naudotoją, šis asmuo turi nustatyti savo vietą."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kad pievienosiet jaunu lietotāju, viņam būs jāizveido savs profils."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lv/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Кога додавате нов корисник, тоа лице треба да го постави својот простор."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mk/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"നിങ്ങളൊരു പുതിയ ഉപയോക്താവിനെ ചേർക്കുമ്പോൾ, ആ വ്യക്തി സ്വന്തം ഇടം സജ്ജീകരിക്കേണ്ടതുണ്ട്."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ml/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Таныг шинэ хэрэглэгч нэмэх үед тухайн хэрэглэгч хувийн орон зайгаа тохируулах шаардлагатай."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mn/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"तुम्ही नवीन वापरकर्त्याला जोडल्यावर, त्या व्यक्तीने त्यांचे स्थान सेट करणे आवश्यक असते."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mr/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Apabila anda menambahkan pengguna baharu, orang itu perlu menyediakan ruang mereka."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ms/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"အသုံးပြုသူအသစ် ထည့်သည့်အခါ ထိုသူသည် မိမိ၏ နေရာကို စီစဉ်သတ်မှတ်ရပါမည်။"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-my/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Når du legger til en ny bruker, må vedkommende konfigurere sitt eget område."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"तपाईंले नयाँ प्रयोगकर्ता थप्दा ती व्यक्तिले आफ्नो स्थान सेटअप गर्नु पर्छ।"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ne/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Wanneer je een nieuwe gebruiker toevoegt, moet die persoon zijn eigen profiel instellen."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nl/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"ଯେତେବେଳେ ଆପଣ ଜଣେ ନୂଆ ୟୁଜର୍ଙ୍କୁ ଯୋଡ଼ିବେ, ସେହି ବ୍ୟକ୍ତିଙ୍କୁ ନିଜ ପାଇଁ ସ୍ପେସ୍ ସେଟଅପ୍ କରିବାକୁ ପଡ଼ିବ।"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-or/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"ਜਦੋਂ ਤੁਸੀਂ ਇੱਕ ਨਵਾਂ ਵਰਤੋਂਕਾਰ ਸ਼ਾਮਲ ਕਰਦੇ ਹੋ, ਤਾਂ ਉਸ ਵਿਅਕਤੀ ਨੂੰ ਆਪਣੀ ਜਗ੍ਹਾ ਸੈੱਟਅੱਪ ਕਰਨ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ।"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pa/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Gdy dodasz nowego użytkownika, musi on skonfigurować swój profil."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pl/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Quando você adiciona um usuário novo, essa pessoa precisa configurar o espaço dela."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Ao adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Quando você adiciona um usuário novo, essa pessoa precisa configurar o espaço dela."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Când adăugați un utilizator nou, acesta trebuie să-și configureze spațiul."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Когда вы добавите пользователя, ему потребуется настроить профиль."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ru/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"ඔබ අලුත් පරිශීලකයෙක් එක් කරන විට, එම පුද්ගලයාට තමන්ගේ ඉඩ සකසා ගැනීමට අවශ්ය වේ."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-si/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Keď pridáte nového používateľa, musí si nastaviť vlastný priestor."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sk/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Ko dodate novega uporabnika, mora ta nastaviti svoj prostor."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kur shton një përdorues të ri, ai person duhet të konfigurojë hapësirën e vet."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sq/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Када додате новог корисника, та особа треба да подеси свој простор."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"När du lägger till en ny användare måste den personen konfigurera sitt utrymme."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sv/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Ukiongeza mtumiaji mpya, ni lazima aweke kikundi chake."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"புதிய பயனரைச் சேர்க்கும்போது, அவர் தனக்கான இடத்தை அமைக்க வேண்டும்."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ta/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"మీరు కొత్త వినియోగదారును జోడించినప్పుడు, ఆ వ్యక్తి తన స్థలాన్ని సెటప్ చేసుకోవాలి."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-te/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"เมื่อคุณเพิ่มผู้ใช้ใหม่ ผู้ใช้ดังกล่าวจะต้องตั้งค่าพื้นที่ของตนเอง"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Kapag nagdagdag ka ng bagong user, kailangang i-set up ng taong iyon ang kanyang espasyo."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tl/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Yeni kullanıcı eklediğinizde, bu kişinin kendi alanını ayarlaması gerekir."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tr/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Коли ви додаєте нового користувача, він має налаштувати свій профіль."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uk/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"جب آپ ایک نیا صارف شامل کرتے ہیں تو اس شخص کو اپنی جگہ کو ترتیب دینے کی ضرورت ہوتی ہے۔"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ur/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Yangi profil qo‘shilgach, uni sozlash lozim."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uz/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Khi bạn thêm một người dùng mới, người đó cần thiết lập không gian của họ."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-vi/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"当您添加新用户时,该用户必须设置自己的空间。"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"新增的使用者需要自行設定個人空間。"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rHK/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"新增的使用者需要自行設定個人空間。"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rTW/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_setup" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_setup" msgid="1791011504259527329">"Uma ungeza umsebenzisi omusha, loyo muntu udinga ukusetha izikhala zakhe."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu/strings_car.xml"
+ line="26"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Enige gebruiker kan programme vir al die ander gebruikers opdateer."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-af/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"ማንኛውም ተጠቃሚ መተግበሪያዎችን ለሌሎች ተጠቃሚዎች ሁሉ ማዘመን ይችላል።"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"يمكن لأي مستخدم تحديث التطبيقات لجميع المستخدمين الآخرين."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ar/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"সকলো ব্য়ৱহাৰকাৰীয়ে অইন ব্য়ৱহাৰকাৰীৰ বাবে এপসমূহ আপডেট কৰিব পাৰে।"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-as/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"İstənilən istifadəçi digər bütün istifadəçilər üçün tətbiqləri güncəlləyə bilər."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-az/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Svaki korisnik može da ažurira aplikacije za sve ostale korisnike."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Кожны карыстальнік прылады можа абнаўляць праграмы для іншых уліковых запісаў."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-be/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Всеки потребител може да актуализира приложенията за всички останали потребители."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"যেকোনও ব্যবহারকারী বাকি সব ব্যবহারকারীর জন্য অ্যাপ আপডেট করতে পারবেন।"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bn/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Svaki korisnik može ažurirati aplikacije za sve druge korisnike."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bs/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Qualsevol usuari pot actualitzar les aplicacions de la resta d\'usuaris."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ca/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Každý uživatel může aktualizovat aplikace všech ostatních uživatelů."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-cs/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Alle brugere kan opdatere apps for alle andre brugere."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-da/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Jeder Nutzer kann Apps für alle anderen Nutzer aktualisieren."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-de/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Οποιοσδήποτε χρήστης μπορεί να ενημερώσει τις εφαρμογές για όλους τους άλλους χρήστες."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-el/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Any user can update apps for all other users."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Any user can update apps for all other users."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Any user can update apps for all other users."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Any user can update apps for all other users."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Any user can update apps for all other users."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Cualquier usuario podrá actualizar las apps de otras personas."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-rUS/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Cualquier usuario puede actualizar las aplicaciones del resto de los usuarios."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Iga kasutaja saab rakendusi värskendada kõigi teiste kasutajate jaoks."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-et/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Edozein erabiltzailek egunera ditzake beste erabiltzaile guztien aplikazioak."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-eu/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"هر کاربری میتواند برنامهها را برای همه کاربران دیگر بهروزرسانی کند."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fa/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Kaikki käyttäjät voivat päivittää muiden käyttäjien sovelluksia."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fi/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Tout utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr-rCA/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"N\'importe quel utilisateur peut mettre à jour les applications pour tous les autres utilisateurs."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Calquera usuario pode actualizar as aplicacións para o resto dos usuarios."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gl/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"કોઈપણ વપરાશકર્તા બધા અન્ય વપરાશકર્તાઓ માટે ઍપને અપડેટ કરી શકે છે."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gu/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"कोई भी उपयोगकर्ता, बाकी सभी उपयोगकर्ताओं के लिए ऐप्लिकेशन अपडेट कर सकते हैं."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hi/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Svaki korisnik može ažurirati aplikacije za ostale korisnike."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Bármely felhasználó frissítheti az alkalmazásokat az összes felhasználó számára."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hu/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Ցանկացած օգտատեր կարող է թարմացնել հավելվածները բոլոր մյուս հաշիվների համար:"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hy/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Setiap pengguna dapat mengupdate aplikasi untuk semua pengguna lain."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-in/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Allir notendur geta uppfært forrit fyrir alla aðra notendur."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-is/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Qualsiasi utente può aggiornare le app per tutti gli altri."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-it/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"כל משתמש יכול לעדכן אפליקציות לכל שאר המשתמשים."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-iw/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"どのユーザーも他のすべてのユーザーに代わってアプリを更新できます。"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ja/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"ნებისმიერ მომხმარებელს შეუძლია აპები ყველა სხვა მომხმარებლისათვის განაახლოს."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ka/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Кез келген пайдаланушы қолданбаларды барлық басқа пайдаланушылар үшін жаңарта алады."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kk/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"អ្នកប្រើប្រាស់ណាក៏អាចដំឡើងជំនាន់កម្មវិធីសម្រាប់អ្នកប្រើប្រាស់ទាំងអស់ផ្សេងទៀតបានដែរ។"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-km/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"ಯಾವುದೇ ಬಳಕೆದಾರರು ಎಲ್ಲಾ ಇತರೆ ಬಳಕೆದಾರರಿಗಾಗಿ ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಬಹುದು."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kn/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"모든 사용자는 다른 사용자를 위해 앱을 업데이트할 수 있습니다."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Колдонмолорду бир колдонуучу калган бардык колдонуучулар үчүн да жаңырта алат."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ky/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"ຜູ້ໃຊ້ຕ່າງໆສາມາດອັບເດດແອັບສຳລັບຜູ້ໃຊ້ອື່ນທັງໝົດໄດ້."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lo/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Bet kuris naudotojas gali atnaujinti visų kitų naudotojų programas."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Ikviens lietotājs var atjaunināt lietotnes citu lietotāju vietā."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lv/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Секој корисник може да ажурира апликации за сите други корисници."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mk/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"ഏതൊരു ഉപയോക്താവിനും മറ്റെല്ലാ ഉപയോക്താക്കൾക്കുമായി ആപ്പുകൾ അപ്ഡേറ്റ് ചെയ്യാനാവും."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ml/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Бусад бүх хэрэглэгчийн аппыг дурын хэрэглэгч шинэчлэх боломжтой."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mn/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"कोणताही वापरकर्ता इतर सर्व वापरकर्त्यांसाठी अॅप्स अपडेट करू शकतो."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mr/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Mana-mana pengguna boleh mengemas kini apl untuk semua pengguna lain."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ms/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"အသုံးပြုသူအားလုံးအတွက် အက်ပ်များကို မည်သူမဆို အပ်ဒိတ်လုပ်နိုင်သည်။"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-my/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Alle brukere kan oppdatere apper for alle andre brukere."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nb/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"सबै प्रयोगकर्ताले अन्य प्रयोगकर्ताका अनुप्रयोगहरू अद्यावधिक गर्न सक्छन्।"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ne/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Elke gebruiker kan apps updaten voor alle andere gebruikers."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nl/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"ଯେକୌଣସି ୟୁଜର୍ ଅନ୍ୟ ସମସ୍ତ ୟୁଜରଙ୍କ ପାଇଁ ଆପ୍କୁ ଅପଡେଟ୍ କରିପାରିବେ।"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-or/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"ਕੋਈ ਵੀ ਵਰਤੋਂਕਾਰ ਹੋਰ ਸਾਰੇ ਵਰਤੋਂਕਾਰਾਂ ਦੀਆਂ ਐਪਾਂ ਨੂੰ ਅੱਪਡੇਟ ਕਰ ਸਕਦਾ ਹੈ।"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pa/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Każdy użytkownik może aktualizować aplikacje wszystkich innych użytkowników."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pl/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Qualquer usuário pode atualizar apps para os demais usuários"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Qualquer utilizador pode atualizar aplicações para todos os outros utilizadores."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Qualquer usuário pode atualizar apps para os demais usuários"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Orice utilizator poate actualiza aplicațiile pentru toți ceilalți utilizatori."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Любой пользователь устройства может обновлять приложения для всех аккаунтов."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ru/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"සියලුම අනෙක් පරිශීලකයින් සඳහා ඕනෑම පරිශීලකයෙකුට යෙදුම් යාවත්කාලීන කළ හැක."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-si/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Akýkoľvek používateľ môže aktualizovať aplikácie všetkých ostatných používateľov."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sk/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Vsak uporabnik lahko posodobi aplikacije za vse druge uporabnike."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Çdo përdorues mund t\'i përditësojë aplikacionet për të gjithë përdoruesit e tjerë."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sq/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Сваки корисник може да ажурира апликације за све остале кориснике."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Alla användare kan uppdatera appar för andra användare."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sv/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Mtumiaji yeyote anaweza kusasisha programu za watumiaji wengine."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"எந்தவொரு பயனரும், மற்ற பயனர்களுக்காக ஆப்ஸைப் புதுப்பிக்கலாம்."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ta/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"ఏ వినియోగదారు అయినా మిగతా అందరు వినియోగదారుల కోసం యాప్లను అప్డేట్ చేయవచ్చు."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-te/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"ผู้ใช้ทุกคนจะอัปเดตแอปให้แก่ผู้ใช้คนอื่นๆ ได้"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Maaaring mag-update ng mga app ang sinumang user para sa lahat ng iba pang user."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tl/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Herhangi bir kullanıcı, diğer tüm kullanıcılar için uygulamaları güncelleyebilir."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tr/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Будь-який користувач може оновлювати додатки для решти людей."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uk/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"کوئی بھی صارف دیگر سبھی صارفین کیلئے ایپس کو اپ ڈیٹ کر سکتا ہے۔"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ur/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Qurilmaning istalgan foydalanuvchisi ilovalarni barcha hisoblar uchun yangilashi mumkin."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uz/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Bất kỳ người dùng nào cũng có thể cập nhật ứng dụng cho tất cả những người dùng khác."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-vi/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"任何用户均可为所有其他用户更新应用。"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"任何使用者都可以為所有其他使用者更新應用程式。"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rHK/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"任何使用者皆可為所有其他使用者更新應用程式。"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rTW/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ExtraTranslation"
+ message=""user_add_user_message_update" is translated here but not found in default locale"
+ errorLine1=" <string name="user_add_user_message_update" msgid="3383320289232716179">"Noma yimuphi umsebenzisi angabuyekeza izinhlelo zokusebenza zabanye abasebenzisi."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu/strings_car.xml"
+ line="27"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_top_boundary_pct" msgid="2520148599096479332">"Top boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="95"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_top_boundary_pct" msgid="2520148599096479332">"Top boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+ line="95"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_top_boundary_pct" msgid="2520148599096479332">"Top boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+ line="95"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_top_boundary_pct" msgid="2520148599096479332">"Top boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="95"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bottom boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="96"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bottom boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+ line="96"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bottom boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+ line="96"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_bottom_boundary_pct" msgid="3880821519814946478">"Bottom boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="96"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="97"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+ line="97"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+ line="97"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_left_boundary_pct" msgid="8502323556112287469">"Left boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="97"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="98"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+ line="98"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> per cent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+ line="98"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_right_boundary_pct" msgid="1201150713021779321">"Right boundary <xliff:g id="PERCENT">%1$d</xliff:g> percent"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="98"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("seconds"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="176"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("seconds"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="176"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("seconds"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+ line="176"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("seconds"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="biometric_dialog_credential_too_many_attempts" msgid="3083141271737748716">"Too many incorrect attempts.\nTry again in <xliff:g id="NUMBER">%d</xliff:g> seconds."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+ line="176"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="224"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+ line="224"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+ line="224"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> percent."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="224"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Battery <xliff:g id="PERCENTAGE">%1$d</xliff:g> per cent; <xliff:g id="TIME">%2$s</xliff:g>"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="225"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Battery <xliff:g id="PERCENTAGE">%1$d</xliff:g> per cent; <xliff:g id="TIME">%2$s</xliff:g>"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+ line="225"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Battery <xliff:g id="PERCENTAGE">%1$d</xliff:g> per cent; <xliff:g id="TIME">%2$s</xliff:g>"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+ line="225"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_with_estimate" msgid="6548654589315074529">"Battery <xliff:g id="PERCENTAGE">%1$d</xliff:g> percent, <xliff:g id="TIME">%2$s</xliff:g>"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="225"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Battery charging, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> percent."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="226"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Battery charging, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> percent."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="226"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Battery charging, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> percent."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+ line="226"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"Battery charging, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> percent."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+ line="226"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Battery <xliff:g id="PERCENTAGE">%d</xliff:g> per cent; charging paused for battery protection."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="227"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Battery <xliff:g id="PERCENTAGE">%d</xliff:g> per cent; charging paused for battery protection."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+ line="227"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Battery <xliff:g id="PERCENTAGE">%d</xliff:g> per cent; charging paused for battery protection."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+ line="227"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_charging_paused" msgid="3560711496775146763">"Battery <xliff:g id="PERCENTAGE">%d</xliff:g> percent, charging paused for battery protection."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="227"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Battery <xliff:g id="PERCENTAGE">%1$d</xliff:g> per cent; <xliff:g id="TIME">%2$s</xliff:g>, charging paused for battery protection."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="228"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Battery <xliff:g id="PERCENTAGE">%1$d</xliff:g> per cent; <xliff:g id="TIME">%2$s</xliff:g>, charging paused for battery protection."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+ line="228"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("per"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Battery <xliff:g id="PERCENTAGE">%1$d</xliff:g> per cent; <xliff:g id="TIME">%2$s</xliff:g>, charging paused for battery protection."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+ line="228"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_charging_paused_with_estimate" msgid="2223541217743647858">"Battery <xliff:g id="PERCENTAGE">%1$d</xliff:g> percent, <xliff:g id="TIME">%2$s</xliff:g>, charging paused for battery protection."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="228"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_top_boundary_pct">Top boundary <xliff:g id="percent" example="50">%1$d</xliff:g> percent</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="251"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_bottom_boundary_pct">Bottom boundary <xliff:g id="percent" example="50">%1$d</xliff:g> percent</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="253"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_left_boundary_pct">Left boundary <xliff:g id="percent" example="50">%1$d</xliff:g> percent</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="255"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="screenshot_right_boundary_pct">Right boundary <xliff:g id="percent" example="50">%1$d</xliff:g> percent</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="257"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("seconds"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="biometric_dialog_credential_too_many_attempts">Too many incorrect attempts.\nTry again in <xliff:g id="number">%d</xliff:g> seconds.</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="429"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level">Battery <xliff:g id="number">%d</xliff:g> percent.</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="535"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_with_estimate">Battery <xliff:g id="percentage" example="95%">%1$d</xliff:g> percent, <xliff:g id="time" example="Until 3:15pm">%2$s</xliff:g></string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="538"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_charging">Battery charging, <xliff:g id="battery_percentage">%d</xliff:g> percent.</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="541"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_charging_paused">Battery <xliff:g id="percentage" example="90%">%d</xliff:g> percent, charging paused for battery protection.</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="544"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("percent"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="accessibility_battery_level_charging_paused_with_estimate">Battery <xliff:g id="percentage" example="90%">%1$d</xliff:g> percent, <xliff:g id="time" example="Until 3:15pm">%2$s</xliff:g>, charging paused for battery protection.</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="547"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("tiles"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="drag_to_remove_disabled" msgid="933046987838658850">"You need at least <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> tiles"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="835"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("tiles"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="drag_to_remove_disabled" msgid="933046987838658850">"You need at least <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> tiles"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="840"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("tiles"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="drag_to_remove_disabled" msgid="933046987838658850">"You need at least <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> tiles"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+ line="840"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("tiles"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="drag_to_remove_disabled" msgid="933046987838658850">"You need at least <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> tiles"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+ line="840"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("devices"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> devices selected"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="1096"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("devices"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> devices selected"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="1101"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("devices"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> devices selected"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+ line="1101"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("devices"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="media_output_dialog_multiple_devices" msgid="1093771040315422350">"<xliff:g id="COUNT">%1$d</xliff:g> devices selected"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+ line="1101"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("characters"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Use fewer than <xliff:g id="LENGTH">%1$d</xliff:g> characters"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="1122"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("characters"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Use fewer than <xliff:g id="LENGTH">%1$d</xliff:g> characters"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="1127"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("characters"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Use fewer than <xliff:g id="LENGTH">%1$d</xliff:g> characters"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+ line="1127"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("characters"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="media_output_broadcast_edit_hint_no_more_than_max" msgid="3923625800037673922">"Use fewer than <xliff:g id="LENGTH">%1$d</xliff:g> characters"</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+ line="1127"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("tiles"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="drag_to_remove_disabled">You need at least <xliff:g id="min_num_tiles" example="6">%1$d</xliff:g> tiles</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="2211"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("devices"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="media_output_dialog_multiple_devices"><xliff:g id="count" example="2">%1$d</xliff:g> devices selected</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="2922"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="PluralsCandidate"
+ message="Formatting %d followed by words ("characters"): This should probably be a plural rather than a string"
+ errorLine1=" <string name="media_output_broadcast_edit_hint_no_more_than_max">Use fewer than <xliff:g id="length" example="16">%1$d</xliff:g> characters</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="2977"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="UnsafeIntentLaunch"
+ message="This intent could be coming from an untrusted source. It is later launched by an unprotected component. You could either make the component protected; or sanitize this intent using androidx.core.content.IntentSanitizer."
+ errorLine1=" final IntentSender intentSender = intent.getParcelableExtra("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java"
+ line="231"
+ column="51"/>
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java"
+ line="239"
+ column="25"
+ message="The unsafe intent is launched here."/>
+ </issue>
+
+ <issue
+ id="ExportedContentProvider"
+ message="Exported content providers can provide access to potentially sensitive data"
+ errorLine1=" <provider android:name=".keyguard.KeyguardSliceProvider" android:authorities="com.android.systemui.keyguard" android:grantUriPermissions="true" android:exported="true">"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+ line="678"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ExportedReceiver"
+ message="Exported receiver does not require permission"
+ errorLine1=" <receiver android:name=".statusbar.KeyboardShortcutsReceiver" android:exported="true">"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+ line="681"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ExportedReceiver"
+ message="Exported receiver does not require permission"
+ errorLine1=" <receiver android:name=".media.dialog.MediaOutputDialogReceiver" android:exported="true">"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+ line="688"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ExportedService"
+ message="Exported service does not require permission"
+ errorLine1=" <service android:name="SystemUIService" android:exported="true"/>"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+ line="381"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ExportedService"
+ message="Exported service does not require permission"
+ errorLine1=" <service android:name=".wallet.controller.WalletContextualLocationsService" android:exported="true"/>"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+ line="382"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ExportedService"
+ message="Exported service does not require permission"
+ errorLine1=" <service android:name=".keyguard.KeyguardService" android:exported="true"/>"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+ line="557"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ExportedService"
+ message="Exported service does not require permission"
+ errorLine1=" <service android:name=".dreams.DreamOverlayService" android:enabled="false" android:exported="true" android:singleUser="true"/>"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+ line="559"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ExpiredTargetSdkVersion"
+ message="Google Play requires that apps target API level 33 or higher."
+ errorLine1=" <uses-sdk android:minSdkVersion="VanillaIceCream" android:targetSdkVersion="16"/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="./out/soong/.intermediates/frameworks/base/packages/SystemUI/SystemUI-core/android_common/f4f47f0509e030e335c57c427145a02a/manifest_fixer/AndroidManifest.xml"
+ line="21"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/AbstractLockscreenShadeTransitionController.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/AdditionalStartable.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/BackupManagerProxy.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/BaseShortcutSection.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/battery/BatterySaverModule.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricOperationInfo.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/model/BiometricPromptRequest.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/BiometricUnlockInteractor.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=" * Copyright (C) 2022 The Android Open Source Project"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogController.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=" * Copyright (C) 2022 The Android Open Source Project"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bluetooth/BroadcastDialogDelegate.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastSender.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/dagger/CarrierTextManagerLog.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalContainer.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/complication/dagger/ComplicationComponent.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/ComplicationComponent.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/ComplicationModule.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/CredentialHeaderViewModel.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/CredentialInteractor.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPasswordView.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialPasswordViewBinder.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialPatternView.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialPatternViewBinder.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/CredentialStatus.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/CredentialView.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/CredentialViewBinder.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/CredentialViewModel.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/communal/ui/view/layout/sections/DefaultCommunalHubSection.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/DefaultTilesRepository.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/DisplayRotation.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/EllipseOverlapDetectorParams.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimates.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/EnhancedEstimatesImpl.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ExpandableOutlineViewBinder.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ExpandableOutlineViewModel.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ExpandableViewBinder.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewmodel/ExpandableViewModel.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/Extensions.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/dagger/FaceAuthLog.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromBouncerToGoneTransition.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToQuickSettingsTransition.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToShadeTransition.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToBouncerTransition.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToGoneTransition.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToQuickSettingsTransition.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromLockscreenToShadeTransition.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromShadeToQuickSettingsTransition.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/utils/GlobalWindowManager.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpModule.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardClockFrame.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardDisplayModule.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardLog.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardStatusAreaView.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardStatusContainer.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardUpdateMonitorLog.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/LargeScreenUtils.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/LockScreenShadeOverScroller.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeScrimTransitionController.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=" * Copyright (C) 2022 The Android Open Source Project"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaDataUtils.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitLogger.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorResultHandler.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesLogger.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/flags/NotOccludedCondition.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryMeter.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryViewWalker.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationPriorityBucket.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLogger.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/PageIndicator.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/PendingRemovalStore.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/PlaceHolderDrawable.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/ProtoDumpable.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/dagger/QSComponent.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSDisableFlagsLogger.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/QSPipelineFlagsRepository.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSRestoreLog.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/dagger/QSScopeModule.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSTileRevealController.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSUtils.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/QsBatteryModeController.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QuickTileLayout.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/ReferenceExt.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/RemainingAttempts.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/model/RestoreData.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/domain/interactor/RestoreReconciliationInteractor.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/rotationlock/RotationLockModule.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/Roundable.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/SafeMarqueeTextView.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotData.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/domain/interactor/SelectedUserInteractor.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtender.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScroller.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateLogger.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHideIconsForBouncerManager.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTransitionAnimatorController.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationSchedulerLogger.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotExecutor.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/TilesSettingConverter.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerSwitch.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/unfold/UnfoldHapticsPlayer.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/unfold/UnfoldKeyguardVisibilityListener.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/UserAutoAddRepository.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/utils/UserRestrictionChecker.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/ui/dialog/UserSwitchDialog.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepository.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/VariableDayDate.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProvider.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/shared/model/WakefulnessModel.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallet/controller/WalletContextualLocationsService.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */"
+ errorLine1=""
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/view/WindowMetricsProvider.kt"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="MissingApacheLicenseDetector"
+ message="License header is missing
Please add the following copyright and license header to the beginning of the file:

/*
 * Copyright (C) 2024 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.
 */">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" Paint pt = new Paint();"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/DessertCaseView.java"
+ line="491"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" final Rect check = new Rect();"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/DessertCaseView.java"
+ line="496"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" mOuterCircle = new Path();"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/MagnifierView.java"
+ line="114"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" mInnerCircle = new Path();"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/MagnifierView.java"
+ line="116"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" Rect scrimRect = new Rect(0, 0, getWidth(), getHeight() / 2);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/MagnifierView.java"
+ line="143"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw operations: Use `Canvas.getClipBounds(Rect)` instead of `Canvas.getClipBounds()` which allocates a temporary `Rect`"
+ errorLine1=" val bounds = canvas.clipBounds"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt"
+ line="63"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" mBarTransitions.setBackgroundFrame(new Rect(0, frameHeight - height, w, h));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java"
+ line="1001"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" Paint paint = new Paint();"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java"
+ line="200"
+ column="23"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" Paint pt = new Paint();"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java"
+ line="151"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" SmartSuggestionMeasures accumulatedMeasures = new SmartSuggestionMeasures("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java"
+ line="240"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" List<View> smartSuggestions = new ArrayList<>(smartActions);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java"
+ line="252"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" List<View> coveredSuggestions = new ArrayList<>();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java"
+ line="254"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" Paint paint = new Paint();"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java"
+ line="141"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" animationViewController?.onSensorRectUpdated(RectF(sensorRect))"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt"
+ line="84"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="WakelockTimeout"
+ message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user's battery."
+ errorLine1=" mWakeLock.acquire();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java"
+ line="395"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WakelockTimeout"
+ message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user's battery."
+ errorLine1=" pmWakeLock.acquire()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/wakelock/ClientTrackingWakeLock.kt"
+ line="41"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WakelockTimeout"
+ message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user's battery."
+ errorLine1=" mShowKeyguardWakeLock.acquire();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="2395"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="WakelockTimeout"
+ message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user's battery."
+ errorLine1=" mWakeLock.acquire();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/NotificationPlayer.java"
+ line="516"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="WakelockTimeout"
+ message="Provide a timeout when requesting a wakelock with `PowerManager.Wakelock.acquire(long timeout)`. This will ensure the OS will cleanup any wakelocks that last longer than you intend, and will save your user's battery."
+ errorLine1=" inner.acquire();"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLock.java"
+ line="134"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="BindServiceOnMainThread"
+ message="This method should be annotated with `@WorkerThread` because it calls bindService"
+ errorLine1=" mContext.bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java"
+ line="179"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="BindServiceOnMainThread"
+ message="This method should be annotated with `@WorkerThread` because it calls unbindService"
+ errorLine1=" mContext.unbindService(mConnection);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/AdminSecondaryLockScreenController.java"
+ line="208"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="BindServiceOnMainThread"
+ message="This method should be annotated with `@WorkerThread` because it calls bindServiceAsUser"
+ errorLine1=" bound = context"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt"
+ line="175"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="BindServiceOnMainThread"
+ message="This method should be annotated with `@WorkerThread` because it calls unbindService"
+ errorLine1=" context.unbindService(serviceConnection)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt"
+ line="210"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="BindServiceOnMainThread"
+ message="This method should be annotated with `@WorkerThread` because it calls bindServiceAsUser"
+ errorLine1=" bindResult = mContext.bindServiceAsUser(mServiceIntent, this, mFlags,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java"
+ line="159"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="BindServiceOnMainThread"
+ message="This method should be annotated with `@WorkerThread` because it calls unbindService"
+ errorLine1=" mContext.unbindService(this);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java"
+ line="164"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="BindServiceOnMainThread"
+ message="This method should be annotated with `@WorkerThread` because it calls unbindService"
+ errorLine1=" mContext.unbindService(this);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/service/ObservableServiceConnection.java"
+ line="234"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="BindServiceOnMainThread"
+ message="This method should be annotated with `@WorkerThread` because it calls bindServiceAsUser"
+ errorLine1=" mBound = mContext.bindServiceAsUser(mQuickStepIntent,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java"
+ line="828"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="BindServiceOnMainThread"
+ message="This method should be annotated with `@WorkerThread` because it calls unbindService"
+ errorLine1=" mContext.unbindService(mOverviewServiceConnection);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java"
+ line="887"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="BindServiceOnMainThread"
+ message="This method should be annotated with `@WorkerThread` because it calls bindServiceAsUser"
+ errorLine1=" return mContext.bindServiceAsUser(mIntent, this, flags, mUser);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java"
+ line="254"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="BindServiceOnMainThread"
+ message="This method should be annotated with `@WorkerThread` because it calls bindServiceAsUser"
+ errorLine1=" return mContext.bindServiceAsUser(mIntent, this,"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java"
+ line="256"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcastAsUser()` should be replaced with `BroadcastSender.sendBroadcastAsUser()`"
+ errorLine1=" sendBroadcastAsUser(intent, UserHandle.SYSTEM, PERMISSION_SELF)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt"
+ line="103"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+ errorLine1=" context.sendBroadcast(mTestIntent);"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java"
+ line="315"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+ errorLine1=" getContext().sendBroadcast(intent);"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+ line="171"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+ errorLine1=" getContext().sendBroadcast(intent);"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+ line="180"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+ errorLine1=" getContext().sendBroadcast(intent);"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+ line="184"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+ errorLine1=" getContext().sendBroadcast(intent);"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+ line="189"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+ errorLine1=" getContext().sendBroadcast(intent);"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+ line="195"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+ errorLine1=" getContext().sendBroadcast(intent);"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/DemoModeFragment.java"
+ line="199"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcastAsUser()` should be replaced with `BroadcastSender.sendBroadcastAsUser()`"
+ errorLine1=" mContext.sendBroadcastAsUser(intent, UserHandle.ALL);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java"
+ line="2207"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcastAsUser()` should be replaced with `BroadcastSender.sendBroadcastAsUser()`"
+ errorLine1=" mContext.sendBroadcastAsUser(USER_PRESENT_INTENT,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="2688"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+ errorLine1=" context.sendBroadcast(intent);"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/widget/PeopleBackupHelper.java"
+ line="505"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+ errorLine1=" getContext().sendBroadcast(intent);"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java"
+ line="199"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+ errorLine1=" sendBroadcast(intent, PERMISSION_SELF);"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java"
+ line="255"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcastAsUser()` should be replaced with `BroadcastSender.sendBroadcastAsUser()`"
+ errorLine1=" context.sendBroadcastAsUser(intent, mUserId);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java"
+ line="157"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+ errorLine1=" context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt"
+ line="83"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+ errorLine1=" mContext.sendBroadcast(new Intent(TunerService.ACTION_CLEAR));"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java"
+ line="317"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="BroadcastSentViaContext"
+ message="`Context.sendBroadcast()` should be replaced with `BroadcastSender.sendBroadcast()`"
+ errorLine1=" sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingActivity.java"
+ line="179"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" notifyDataSetChanged()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt"
+ line="131"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/hearingaid/HearingDevicesListAdapter.java"
+ line="77"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java"
+ line="116"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" mAdapter.notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java"
+ line="840"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/LockscreenFragment.java"
+ line="299"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+ line="69"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+ line="475"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+ line="488"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java"
+ line="224"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java"
+ line="275"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java"
+ line="484"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java"
+ line="505"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java"
+ line="513"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumePanelSlicesAdapter.java"
+ line="89"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletCardCarousel.java"
+ line="433"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" registerReceiver(mBroadcastReceiver, mIntentFilter, PERMISSION_SELF, null,"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/appclips/AppClipsActivity.java"
+ line="136"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" context.registerReceiver(mBroadcastReceiver, filter, Context.RECEIVER_EXPORTED_UNAUDITED);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java"
+ line="807"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" Intent intent = mContext.registerReceiver("
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java"
+ line="160"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiver(mBroadcastReceiver, intentFilter,"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/BiometricNotificationService.java"
+ line="177"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" Intent i = getContext().registerReceiver(null,"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java"
+ line="379"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiver(mBannerActionBroadcastReceiver, internalFilter, PERMISSION_SELF,"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+ line="929"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" context.registerReceiver("
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt"
+ line="233"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" context.registerReceiver(mReceiver, filter,"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/CsdWarningDialog.java"
+ line="132"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiver(mReceiver, filter);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayRegistrant.java"
+ line="125"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiver(mReceiver, filter, null, null,"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsClassicDebug.java"
+ line="146"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiver(mReceiver,"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java"
+ line="469"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_DISABLE_ESIM),"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardEsimArea.java"
+ line="98"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" getContext().registerReceiver(mIntentReceiver, filter, null /* permission*/,"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java"
+ line="401"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" context.registerReceiver(new BroadcastReceiver() {"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java"
+ line="145"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiver(mDelayedLockBroadcastReceiver, delayedActionFilter,"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java"
+ line="1524"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" context.registerReceiver(appChangeReceiver, uninstallFilter)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImpl.kt"
+ line="349"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" context.registerReceiver(appChangeReceiver, uninstallFilter)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessor.kt"
+ line="288"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" getContext().registerReceiver(mNotificationActionReceiver, intentFilter,"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/MenuViewLayer.java"
+ line="631"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, overlayFilter, null, null);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationModeController.java"
+ line="119"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiver(mBaseBroadcastReceiver, internalFilter, PERMISSION_SELF, null,"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java"
+ line="432"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiver(mLauncherStateChangedReceiver, filter);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java"
+ line="663"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiver(mReceiver, filter, Context.RECEIVER_EXPORTED);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/service/PackageObserver.java"
+ line="91"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiver(mBaseBroadcastReceiver, perAppFilter);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java"
+ line="243"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiver(mBaseBroadcastReceiver, bootComplete);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java"
+ line="247"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" getContext().registerReceiver(mReceiver, filter);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java"
+ line="64"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" getContext().registerReceiver(mReceiver, filter);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/PluginFragment.java"
+ line="66"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiverAsUser(this, UserHandle.ALL, filter,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java"
+ line="827"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" Intent intent = mContext.registerReceiver("
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/power/PowerUI.java"
+ line="297"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiver(mPermControllerChangeReceiver, PKG_CHANGE_INTENT_FILTER);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SafetyController.java"
+ line="81"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" context.registerReceiver(mReceiver, filter,"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/SafetyWarningDialog.java"
+ line="66"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" context.registerReceiver(this, filter,"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java"
+ line="142"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" getContext().registerReceiverAsUser(mIntentReceiver, UserHandle.ALL, filter, null, null);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitClockView.java"
+ line="78"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiverAsUser(mChallengeReceiver, UserHandle.ALL,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java"
+ line="103"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" context.registerReceiverAsUser("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt"
+ line="79"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiverForAllUsers("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java"
+ line="229"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" registerReceiver(mCloseSystemDialogs, new IntentFilter(ACTION_CLOSE_SYSTEM_DIALOGS),"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java"
+ line="130"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiverAsUser("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java"
+ line="439"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" context.registerReceiverAsUser(mUninstallReceiver, userTracker.getUserHandle(), filter,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java"
+ line="100"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" context.registerReceiver(mBroadcastReceiver, filter,"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java"
+ line="774"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" activity.registerReceiver(this, filter);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbDisconnectedReceiver.java"
+ line="40"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" activity.registerReceiver(this, filter);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/usb/UsbDisconnectedReceiver.java"
+ line="48"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" context.registerReceiverAsUser("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt"
+ line="134"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java"
+ line="78"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" context.registerReceiverForAllUsers(this, filter, null, backgroundHandler)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt"
+ line="148"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" registerReceiver(mWifiChangeReceiver, filter);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingActivity.java"
+ line="177"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" registerReceiver(mWifiChangeReceiver, filter);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingSecondaryUserActivity.java"
+ line="98"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="RegisterReceiverViaContext"
+ message="Register `BroadcastReceiver` using `BroadcastDispatcher` instead of `Context`"
+ errorLine1=" mContext.registerReceiver(mScreenOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java"
+ line="402"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow<Int>(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/assist/data/repository/AssistRepository.kt"
+ line="29"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val mutableIsExpanded = MutableSharedFlow<Boolean>()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt"
+ line="78"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val _onAuthenticationResult = MutableSharedFlow<Boolean>()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt"
+ line="129"
+ column="43"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow(extraBufferCapacity = 1)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt"
+ line="81"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow(extraBufferCapacity = 1)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/BluetoothTileDialogDelegate.kt"
+ line="86"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val _onIncorrectBouncerInput = MutableSharedFlow<Unit>()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt"
+ line="64"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val _onImeHiddenByUser = MutableSharedFlow<Unit>()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt"
+ line="84"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val resetToDefault = MutableSharedFlow<Unit>(replay = 1)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerMessageViewModel.kt"
+ line="107"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(scope, SharingStarted.WhileSubscribed(), replay = 1)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/component/captioning/domain/CaptioningAvailabilityCriteria.kt"
+ line="48"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(scope, SharingStarted.WhileSubscribed())"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/CarrierConfigRepository.kt"
+ line="93"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(scope, SharingStarted.WhileSubscribed(), replay = 1)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/ColorCorrectionRepository.kt"
+ line="69"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(scope, SharingStarted.WhileSubscribed(), replay = 1)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/ColorInversionRepository.kt"
+ line="69"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val _appWidgetIdToRemove = MutableSharedFlow<Int>()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalAppWidgetHost.kt"
+ line="45"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn("
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt"
+ line="142"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow(extraBufferCapacity = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt"
+ line="165"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn("
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt"
+ line="236"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(scope = applicationScope, started = SharingStarted.WhileSubscribed())"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalTutorialRepository.kt"
+ line="94"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(coroutineScope, SharingStarted.Eagerly, replay = 1)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/domain/interactor/ComponentsInteractor.kt"
+ line="67"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(scope, SharingStarted.WhileSubscribed())"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt"
+ line="157"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val _validatedAttestation: MutableSharedFlow<ByteArray?> = MutableSharedFlow()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/CredentialViewModel.kt"
+ line="92"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(tileScope, SharingStarted.WhileSubscribed())"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileDataInteractor.kt"
+ line="91"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow<DefaultsRequest>("
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileDefaultsRepository.kt"
+ line="77"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(applicationScope, SharingStarted.WhileSubscribed(), replay = 1)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileDefaultsRepository.kt"
+ line="93"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow<Tile>(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileInteractor.kt"
+ line="55"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(tileScope, SharingStarted.WhileSubscribed())"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTilePackageUpdatesRepository.kt"
+ line="71"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow<TileWithUser>(onBufferOverflow = BufferOverflow.DROP_OLDEST, replay = 1)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/data/repository/CustomTileRepository.kt"
+ line="111"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" val mutableRefreshEvents = MutableSharedFlow<Unit>()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/custom/domain/interactor/CustomTileServiceInteractor.kt"
+ line="183"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" val demoModeFinishedEvent = MutableSharedFlow<Unit>(extraBufferCapacity = 1)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepository.kt"
+ line="75"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" val mobileEvents = _mobileCommands.shareIn(scope, SharingStarted.WhileSubscribed())"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoModeMobileConnectionDataSource.kt"
+ line="56"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" val wifiEvents = _wifiCommands.shareIn(scope, SharingStarted.WhileSubscribed())"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/demo/DemoModeWifiDataSource.kt"
+ line="44"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(scope, SharingStarted.WhileSubscribed())"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt"
+ line="85"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val attemptEnterDeviceFromDeviceEntryIcon: MutableSharedFlow<Unit> = MutableSharedFlow()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntrySourceInteractor.kt"
+ line="54"
+ column="82"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow(extraBufferCapacity = 1)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/DeviceItemInteractor.kt"
+ line="62"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(bgApplicationScope, started = SharingStarted.WhileSubscribed(), replay = 1)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt"
+ line="147"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(this, started = Lazily)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/HideNotificationsBinder.kt"
+ line="39"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow<Long>(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/dreams/homecontrols/domain/interactor/HomeControlsComponentInteractor.kt"
+ line="138"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(backgroundScope, SharingStarted.WhileSubscribed(), replay = 1)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/InstalledTilesComponentRepository.kt"
+ line="84"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" val refreshTransition = MutableSharedFlow<Config>(extraBufferCapacity = 1)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBlueprintRepository.kt"
+ line="59"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val _keyguardAuthenticatedPrimaryAuth = MutableSharedFlow<Int>()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt"
+ line="178"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val _userRequestedBouncerWhenAlreadyAuthenticated = MutableSharedFlow<Int>()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt"
+ line="183"
+ column="65"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val unseenEntryAdded = MutableSharedFlow<NotificationEntry>(extraBufferCapacity = 1)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt"
+ line="96"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val unseenEntryRemoved = MutableSharedFlow<NotificationEntry>(extraBufferCapacity = 1)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.kt"
+ line="97"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val _keyguardDone: MutableSharedFlow<KeyguardDone> = MutableSharedFlow()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt"
+ line="298"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" override val keyguardDoneAnimationsFinished: MutableSharedFlow<Unit> = MutableSharedFlow()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt"
+ line="304"
+ column="76"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow<Float>("
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt"
+ line="81"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(scope, SharingStarted.Eagerly)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt"
+ line="106"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow<TransitionStep>("
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt"
+ line="149"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(scope, SharingStarted.Eagerly, replay = 1)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt"
+ line="193"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(scope, SharingStarted.Eagerly, replay = 1)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt"
+ line="207"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(scope, SharingStarted.Eagerly, replay = 1)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt"
+ line="249"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow<TransitionStep>("
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt"
+ line="117"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(applicationScope, started = SharingStarted.Eagerly, replay = 1)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/LogContextInteractor.kt"
+ line="130"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(coroutineScope, SharingStarted.Eagerly, replay = 1)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt"
+ line="63"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(coroutineScope, SharingStarted.Eagerly, replay = 1)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt"
+ line="93"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow<PackageChangeModel>(replay = 0, extraBufferCapacity = BUFFER_CAPACITY)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/common/data/repository/PackageUpdateMonitor.kt"
+ line="67"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val _accessibilityHint = MutableSharedFlow<String>()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt"
+ line="143"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow<Int>("
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/ui/adapter/QSSceneAdapter.kt"
+ line="179"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(scope, SharingStarted.Eagerly)"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/QSSettingsRestoredRepository.kt"
+ line="123"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val userInputs: MutableSharedFlow<QSTileUserAction> = MutableSharedFlow()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt"
+ line="89"
+ column="67"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val forceUpdates: MutableSharedFlow<Unit> = MutableSharedFlow()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt"
+ line="90"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn("
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt"
+ line="104"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(tileScope, SharingStarted.WhileSubscribed())"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt"
+ line="162"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn("
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/base/viewmodel/QSTileViewModelImpl.kt"
+ line="172"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(applicationScope, SharingStarted.WhileSubscribed())"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/brightness/data/repository/ScreenBrightnessRepository.kt"
+ line="150"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(applicationScope, SharingStarted.WhileSubscribed())"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/brightness/data/repository/ScreenBrightnessRepository.kt"
+ line="156"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn(applicationScope, SharingStarted.WhileSubscribed())"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/brightness/data/repository/ScreenBrightnessRepository.kt"
+ line="169"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val _notificationStackChanged = MutableSharedFlow<Unit>(extraBufferCapacity = 1)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/domain/interactor/SharedNotificationContainerInteractor.kt"
+ line="57"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val _bouncerMessageChanged = MutableSharedFlow<String?>()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/SimBouncerInteractor.kt"
+ line="75"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val changes = MutableSharedFlow<Unit>()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/component/spatial/domain/interactor/SpatialAudioComponentInteractor.kt"
+ line="54"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn("
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/data/repository/UserA11yQsShortcutsRepository.kt"
+ line="56"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" private val changeEvents = MutableSharedFlow<ChangeAction>("
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/UserAutoAddRepository.kt"
+ line="47"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow<ChangeAction>(extraBufferCapacity = CHANGES_BUFFER_SIZE)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/repository/UserTileSpecRepository.kt"
+ line="54"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`shareIn()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" .shareIn("
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/panel/ui/viewmodel/VolumePanelViewModel.kt"
+ line="107"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SharedFlowCreation"
+ message="`MutableSharedFlow()` creates a new shared flow, which has poor performance characteristics"
+ errorLine1=" MutableSharedFlow<Int>(extraBufferCapacity = QSSettingsRestoredRepository.BUFFER_CAPACITY)"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/pipeline/data/restoreprocessors/WorkTileRestoreProcessor.kt"
+ line="49"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SlowUserIdQuery"
+ message="Use `UserTracker.getUserId()` instead of `ActivityManager.getCurrentUser()`"
+ errorLine1=" mAudioManager.playSoundEffect(soundConstant, ActivityManager.getCurrentUser());"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonView.java"
+ line="373"
+ column="70"/>
+ </issue>
+
+ <issue
+ id="SlowUserIdQuery"
+ message="Use `UserTracker.getUserId()` instead of `ActivityManager.getCurrentUser()`"
+ errorLine1=" startActivityAsUser(intent, UserHandle.of(ActivityManager.getCurrentUser()));"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/permission/MediaProjectionPermissionActivity.java"
+ line="373"
+ column="75"/>
+ </issue>
+
+ <issue
+ id="SlowUserIdQuery"
+ message="Use `UserTracker.getUserId()` instead of `ActivityManager.getCurrentUser()`"
+ errorLine1=" int startingUser = ActivityManager.getCurrentUser();"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/settings/MultiUserUtilsModule.java"
+ line="70"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="SlowUserIdQuery"
+ message="Use `UserTracker.getUserId()` instead of `ActivityManager.getCurrentUser()`"
+ errorLine1=" ? UserHandle.of(ActivityManager.getCurrentUser()) : notificationUser;"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java"
+ line="611"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="SlowUserIdQuery"
+ message="Use `UserTracker.getUserId()` instead of `ActivityManager.getCurrentUser()`"
+ errorLine1=" ActivityManager.getCurrentUser());"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitClockView.java"
+ line="91"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="SlowUserIdQuery"
+ message="Use `UserTracker.getUserId()` instead of `ActivityManager.getCurrentUser()`"
+ errorLine1=" TextUtils.join(",", hideList), ActivityManager.getCurrentUser());"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/StatusBarSwitch.java"
+ line="86"
+ column="64"/>
+ </issue>
+
+ <issue
+ id="SlowUserIdQuery"
+ message="Use `UserTracker.getUserId()` instead of `ActivityManager.getCurrentUser()`"
+ errorLine1=" ActivityManager.getCurrentUser(),"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/stylus/StylusUsiPowerUI.kt"
+ line="236"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="SlowUserInfoQuery"
+ message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+ errorLine1=" getUserInfo("
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/CredentialInteractor.kt"
+ line="173"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="SlowUserInfoQuery"
+ message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+ errorLine1=" manager.getUserInfo(lastSelectedNonGuestUserHandle)"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/domain/interactor/GuestUserInteractor.kt"
+ line="149"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="SlowUserInfoQuery"
+ message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+ errorLine1=" mUserManager.getUserInfo(userId).isManagedProfile()"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java"
+ line="500"
+ column="30"/>
+ </issue>
+
+ <issue
+ id="SlowUserInfoQuery"
+ message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+ errorLine1=" val userType = userManager.getUserInfo(userId).userType"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/data/repository/ProfileTypeRepositoryImpl.kt"
+ line="45"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="SlowUserInfoQuery"
+ message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+ errorLine1=" userManager.getUserInfo(it.taskInfo1.userId).toUserType(),"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt"
+ line="66"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="SlowUserInfoQuery"
+ message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+ errorLine1=" userManager.getUserInfo(it.taskInfo2!!.userId).toUserType(),"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/data/RecentTaskListProvider.kt"
+ line="75"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="SlowUserInfoQuery"
+ message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+ errorLine1=" return mUserManager.getUserInfo(mCurrentUserId).isRestricted()"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java"
+ line="312"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="SlowUserInfoQuery"
+ message="Use `UserTracker.getUserInfo()` instead of `UserManager.getUserInfo()`"
+ errorLine1=" final UserInfo newUserInfo = mUserManager.getUserInfo(newUserId);"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java"
+ line="386"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="SoftwareBitmap"
+ message="Replace software bitmap with `Config.HARDWARE`"
+ errorLine1=" Bitmap a = Bitmap.createBitmap(b.getWidth(), b.getHeight(), Bitmap.Config.ALPHA_8);"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/DessertCaseView.java"
+ line="196"
+ column="83"/>
+ </issue>
+
+ <issue
+ id="SoftwareBitmap"
+ message="Replace software bitmap with `Config.HARDWARE`"
+ errorLine1=" ?: Bitmap.Config.ARGB_8888"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt"
+ line="95"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="SoftwareBitmap"
+ message="Replace software bitmap with `Config.HARDWARE`"
+ errorLine1=" ?: Bitmap.Config.ARGB_8888"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt"
+ line="95"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="SoftwareBitmap"
+ message="Replace software bitmap with `Config.HARDWARE`"
+ errorLine1=" Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayDotImageView.java"
+ line="120"
+ column="78"/>
+ </issue>
+
+ <issue
+ id="SoftwareBitmap"
+ message="Replace software bitmap with `Config.HARDWARE`"
+ errorLine1=" drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowDragController.java"
+ line="182"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="SoftwareBitmap"
+ message="Replace software bitmap with `Config.HARDWARE`"
+ errorLine1=" Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonDrawable.java"
+ line="329"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="SoftwareBitmap"
+ message="Replace software bitmap with `Config.HARDWARE`"
+ errorLine1=" Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonDrawable.java"
+ line="357"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="SoftwareBitmap"
+ message="Replace software bitmap with `Config.HARDWARE`"
+ errorLine1=" shortcutKeyIconItemHeightWidth, Bitmap.Config.ARGB_8888);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java"
+ line="686"
+ column="79"/>
+ </issue>
+
+ <issue
+ id="SoftwareBitmap"
+ message="Replace software bitmap with `Config.HARDWARE`"
+ errorLine1=" Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java"
+ line="451"
+ column="92"/>
+ </issue>
+
+ <issue
+ id="SoftwareBitmap"
+ message="Replace software bitmap with `Config.HARDWARE`"
+ errorLine1=" : Bitmap.Config.RGB_565;"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java"
+ line="452"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="SoftwareBitmap"
+ message="Replace software bitmap with `Config.HARDWARE`"
+ errorLine1=" bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java"
+ line="355"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="SoftwareBitmap"
+ message="Replace software bitmap with `Config.HARDWARE`"
+ errorLine1=" drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java"
+ line="359"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="Recycle"
+ message="This `TypedArray` should be recycled after use with `#recycle()`"
+ errorLine1=" TypedArray typedArray = context.obtainStyledAttributes("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/common/ui/view/SeekBarWithIconButtonsView.java"
+ line="85"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="Recycle"
+ message="This `TypedArray` should be recycled after use with `#recycle()`"
+ errorLine1=" final TypedArray sa = mResources.obtainAttributes(mAttrs, R.styleable.Shortcut);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/ShortcutParser.java"
+ line="103"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `FrameLayout`: `layout_weight`"
+ errorLine1=" android:layout_weight="0""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/contextual.xml"
+ line="31"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `FrameLayout`: `layout_weight`"
+ errorLine1=" android:layout_weight="0""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/contextual.xml"
+ line="54"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param '`layout_weight`' (included from within a `FrameLayout` in `layout/controls_dialog.xml`)"
+ errorLine1=" android:layout_weight="1""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/controls_base_item.xml"
+ line="21"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+ line="44"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_alignParentStart`"
+ errorLine1=" android:layout_alignParentStart="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+ line="45"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+ line="54"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_alignEnd`"
+ errorLine1=" android:layout_alignEnd="@id/pkg_icon""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+ line="56"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_toEndOf`"
+ errorLine1=" android:layout_toEndOf="@id/pkg_icon">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+ line="57"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param '`layout_weight`' (included from within a `FrameLayout` in `layout/contextual.xml`, included from within a `FrameLayout` in `layout/menu_ime.xml`)"
+ errorLine1=" android:layout_weight="0""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/ime_switcher.xml"
+ line="23"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="false""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="44"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_alignParentStart`"
+ errorLine1=" android:layout_alignParentStart="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="45"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="104"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_alignEnd`"
+ errorLine1=" android:layout_alignEnd="@id/conversation_icon""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="106"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_toEndOf`"
+ errorLine1=" android:layout_toEndOf="@id/conversation_icon">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="107"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="124"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="157"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="173"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_alignParentEnd`"
+ errorLine1=" android:layout_alignParentEnd="true" />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="178"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_toEndOf`"
+ errorLine1=" android:layout_toEndOf="@id/silence_icon""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="353"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="43"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_alignParentStart`"
+ errorLine1=" android:layout_alignParentStart="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="44"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="53"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_alignEnd`"
+ errorLine1=" android:layout_alignEnd="@id/pkg_icon""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="55"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_toEndOf`"
+ errorLine1=" android:layout_toEndOf="@id/pkg_icon">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="56"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="82"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="100"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_toStartOf`"
+ errorLine1=" android:layout_toStartOf="@id/info""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="105"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="111"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_alignParentEnd`"
+ errorLine1=" android:layout_alignParentEnd="true" />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="116"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_toEndOf`"
+ errorLine1=" android:layout_toEndOf="@id/silence_icon""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="301"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+ line="42"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_alignParentStart`"
+ errorLine1=" android:layout_alignParentStart="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+ line="43"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+ line="52"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_alignEnd`"
+ errorLine1=" android:layout_alignEnd="@id/conversation_icon""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+ line="54"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_toEndOf`"
+ errorLine1=" android:layout_toEndOf="@id/conversation_icon">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+ line="55"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+ line="67"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+ line="83"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_alignParentEnd`"
+ errorLine1=" android:layout_alignParentEnd="true"/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+ line="88"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+ line="124"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+ line="131"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_above`"
+ errorLine1=" android:layout_above="@id/got_it_button">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml"
+ line="75"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_item_v2.xml"
+ line="46"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_item_v2.xml"
+ line="55"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_centerVertical`"
+ errorLine1=" android:layout_centerVertical="true""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_item_v2.xml"
+ line="75"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="ObsoleteSdkInt"
+ message="Unnecessary; SDK_INT is always >= 34"
+ errorLine1=" @RequiresApi(34)"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java"
+ line="531"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="StaticFieldLeak"
+ message="Do not place Android context classes in static fields (static reference to `SystemUIDialog` which has field `mContext` pointing to `Context`); this is a memory leak"
+ errorLine1=" var dialog: SystemUIDialog? = null"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogManager.kt"
+ line="40"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="StaticFieldLeak"
+ message="This `AsyncTask` class should be static or leaks might occur (anonymous android.os.AsyncTask)"
+ errorLine1=" new AsyncTask<Icon, Void, Drawable>() {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonView.java"
+ line="207"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="StaticFieldLeak"
+ message="Do not place Android context classes in static fields (static reference to `KeyboardShortcutListSearch` which has field `mSearchEditText` pointing to `EditText`); this is a memory leak"
+ errorLine1=" @VisibleForTesting static KeyboardShortcutListSearch sInstance;"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcutListSearch.java"
+ line="100"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="StaticFieldLeak"
+ message="Do not place Android context classes in static fields (static reference to `KeyboardShortcuts` which has field `mContext` pointing to `Context`); this is a memory leak"
+ errorLine1=" @VisibleForTesting static KeyboardShortcuts sInstance;"
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java"
+ line="83"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="StaticFieldLeak"
+ message="Do not place Android context classes in static fields (static reference to `MediaOutputDialog` which has field `mContext` pointing to `Context`); this is a memory leak"
+ errorLine1=" var mediaOutputDialog: MediaOutputDialog? = null"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogManager.kt"
+ line="41"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="StaticFieldLeak"
+ message="This `AsyncTask` class should be static or leaks might occur (anonymous android.os.AsyncTask)"
+ errorLine1=" new AsyncTask<Void, Void, Void>() {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java"
+ line="742"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="StaticFieldLeak"
+ message="This field leaks a context object"
+ errorLine1=" private final Context mContext;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java"
+ line="1053"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="StaticFieldLeak"
+ message="This field leaks a context object"
+ errorLine1=" private ExpandableNotificationRow mRow;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java"
+ line="1062"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="StaticFieldLeak"
+ message="This field leaks a context object"
+ errorLine1=" private final Context mContext;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java"
+ line="62"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="StaticFieldLeak"
+ message="Do not place Android context classes in static fields (static reference to `SystemUIInitializer` which has field `mContext` pointing to `Context`); this is a memory leak"
+ errorLine1=" // Must be static due to http://b/141008541."
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.kt"
+ line="48"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="StaticFieldLeak"
+ message="This `AsyncTask` class should be static or leaks might occur (anonymous android.os.AsyncTask)"
+ errorLine1=" mUserInfoTask = new AsyncTask<Void, Void, UserInfoQueryResult>() {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java"
+ line="147"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="UseCompoundDrawables"
+ message="This tag and its children can be replaced by one `<TextView/>` and a compound drawable"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_session_end_dialog.xml"
+ line="26"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="UseCompoundDrawables"
+ message="This tag and its children can be replaced by one `<TextView/>` and a compound drawable"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+ line="112"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="UseCompoundDrawables"
+ message="This tag and its children can be replaced by one `<TextView/>` and a compound drawable"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_space_initial_layout.xml"
+ line="36"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="UseCompoundDrawables"
+ message="This tag and its children can be replaced by one `<TextView/>` and a compound drawable"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_with_content.xml"
+ line="95"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (922 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M36.3,25.5c-0.4,-0.3,-1,-0.5,-1.5,-0.5c-0.1,0,-0.3,0,-0.4,0c-0.3,0,-0.5,0,-0.7,0.1c-0.6,0.1,-1.1,0.4,-1.5,0.8 c-0.8,0.6,-1.2,1.6,-1.2,2.7v3.5h-1.2V14c0,-1.4,-0.6,-2.7,-1.6,-3.6c-0.4,-0.4,-0.9,-0.8,-1.5,-1c-0.4,-0.1,-0.7,-0.2,-1.1,-0.3 C25.2,9,24.9,9,24.7,9s-0.5,0,-0.8,0.1c-0.4,0.1,-0.8,0.2,-1.1,0.3c-0.6,0.2,-1.1,0.6,-1.5,1c-1,0.9,-1.6,2.2,-1.6,3.6v10.3h-2.4v-4.5 c0,-1.2,-0.6,-2.2,-1.5,-2.8c-0.4,-0.3,-1,-0.5,-1.5,-0.6c-0.2,0,-0.3,-0.1,-0.5,-0.1c-0.2,0,-0.4,0,-0.6,0.1c-0.6,0.1,-1.1,0.3,-1.5,0.7 c-0.8,0.6,-1.4,1.6,-1.4,2.7v8c0,1.1,0.5,2.1,1.4,2.7c0.4,0.3,0.9,0.6,1.5,0.7c0.2,0,0.4,0.1,0.6,0.1h0.5h1.5h3.8V48 c0,1.4,0.6,2.7,1.6,3.6c0.4,0.4,0.9,0.8,1.5,1c0.4,0.1,0.7,0.2,1.1,0.3c0.2,0,0.5,0.1,0.8,0.1s0.5,0,0.8,-0.1 c0.4,-0.1,0.8,-0.2,1.1,-0.3c0.6,-0.2,1.1,-0.6,1.5,-1c1,-0.9,1.6,-2.2,1.6,-3.6v-9.1h1.2h1.2h1.5h0.7c0.1,0,0.3,0,0.4,0 c0.6,-0.1,1.1,-0.2,1.5,-0.5c0.9,-0.6,1.6,-1.7,1.6,-2.9v-7C37.9,27.2,37.3,26.1,36.3,25.5z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable-nodpi/cactus1.xml"
+ line="22"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (983 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M19.400000,10.000000c-0.700000,-3.400000 -3.700000,-6.000000 -7.400000,-6.000000c-1.500000,0.000000 -2.900000,0.400000 -4.000000,1.200000l1.500000,1.500000C10.200000,6.200000 11.100000,6.000000 12.000000,6.000000c3.000000,0.000000 5.500000,2.500000 5.500000,5.500000L17.500000,12.000000L19.000000,12.000000c1.700000,0.000000 3.000000,1.300000 3.000000,3.000000c0.000000,1.100000 -0.600000,2.100000 -1.600000,2.600000l1.500000,1.500000c1.300000,-0.900000 2.100000,-2.400000 2.100000,-4.100000C24.000000,12.400000 21.900000,10.200000 19.400000,10.000000zM3.000000,5.300000L5.800000,8.000000C2.600000,8.200000 0.000000,10.800000 0.000000,14.000000c0.000000,3.300000 2.700000,6.000000 6.000000,6.000000l11.700000,0.000000l2.000000,2.000000l1.300000,-1.300000L4.300000,4.000000L3.000000,5.300000zM7.700000,10.000000l8.000000,8.000000L6.000000,18.000000c-2.200000,0.000000 -4.000000,-1.800000 -4.000000,-4.000000c0.000000,-2.200000 1.800000,-4.000000 4.000000,-4.000000L7.700000,10.000000z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable-nodpi/cloud_off.xml"
+ line="22"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (983 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M19.400000,10.000000c-0.700000,-3.400000 -3.700000,-6.000000 -7.400000,-6.000000c-1.500000,0.000000 -2.900000,0.400000 -4.000000,1.200000l1.500000,1.500000C10.200000,6.200000 11.100000,6.000000 12.000000,6.000000c3.000000,0.000000 5.500000,2.500000 5.500000,5.500000L17.500000,12.000000L19.000000,12.000000c1.700000,0.000000 3.000000,1.300000 3.000000,3.000000c0.000000,1.100000 -0.600000,2.100000 -1.600000,2.600000l1.500000,1.500000c1.300000,-0.900000 2.100000,-2.400000 2.100000,-4.100000C24.000000,12.400000 21.900000,10.200000 19.400000,10.000000zM3.000000,5.300000L5.800000,8.000000C2.600000,8.200000 0.000000,10.800000 0.000000,14.000000c0.000000,3.300000 2.700000,6.000000 6.000000,6.000000l11.700000,0.000000l2.000000,2.000000l1.300000,-1.300000L4.300000,4.000000L3.000000,5.300000zM7.700000,10.000000l8.000000,8.000000L6.000000,18.000000c-2.200000,0.000000 -4.000000,-1.800000 -4.000000,-4.000000c0.000000,-2.200000 1.800000,-4.000000 4.000000,-4.000000L7.700000,10.000000z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/cloud_off.xml"
+ line="22"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (925 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M34.4,43.95Q31.55,43.95 29.45,42.4Q27.35,40.85 26.35,38.3Q25.35,35.75 24.375,34.325Q23.4,32.9 20.7,30.75Q17.4,28.1 15.95,25.1Q14.5,22.1 14.5,17.8Q14.5,11.8 18.3,7.975Q22.1,4.15 28.1,4.15Q34,4.15 37.875,7.825Q41.75,11.5 42,17.2H39Q38.75,12.8 35.725,9.975Q32.7,7.15 28.1,7.15Q23.6,7.15 20.55,10.225Q17.5,13.3 17.5,17.8Q17.5,21.4 18.9,24.025Q20.3,26.65 23.55,29.1Q25.5,30.55 26.675,32.25Q27.85,33.95 28.9,36.45Q29.75,38.55 31.125,39.75Q32.5,40.95 34.4,40.95Q36.15,40.95 37.425,39.75Q38.7,38.55 38.95,36.8H41.95Q41.7,39.8 39.55,41.875Q37.4,43.95 34.4,43.95ZM11.95,32.9Q9.1,29.75 7.55,25.825Q6,21.9 6,17.6Q6,13.35 7.475,9.375Q8.95,5.4 11.95,2.35L14.2,4.35Q11.6,7 10.3,10.425Q9,13.85 9,17.6Q9,21.3 10.325,24.725Q11.65,28.15 14.2,30.85ZM28.1,22.45Q26.15,22.45 24.8,21.1Q23.45,19.75 23.45,17.8Q23.45,15.85 24.8,14.45Q26.15,13.05 28.1,13.05Q30.05,13.05 31.45,14.45Q32.85,15.85 32.85,17.8Q32.85,19.75 31.45,21.1Q30.05,22.45 28.1,22.45Z"/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/hearing.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1848 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M6.000000,18.000000c0.000000,0.600000 0.400000,1.000000 1.000000,1.000000l1.000000,0.000000l0.000000,3.500000C8.000000,23.299999 8.700000,24.000000 9.500000,24.000000c0.800000,0.000000 1.500000,-0.700000 1.500000,-1.500000L11.000000,19.000000l2.000000,0.000000l0.000000,3.500000c0.000000,0.800000 0.700000,1.500000 1.500000,1.500000c0.800000,0.000000 1.500000,-0.700000 1.500000,-1.500000L16.000000,19.000000l1.000000,0.000000c0.600000,0.000000 1.000000,-0.400000 1.000000,-1.000000L18.000000,8.000000L6.000000,8.000000L6.000000,18.000000zM3.500000,8.000000C2.700000,8.000000 2.000000,8.700000 2.000000,9.500000l0.000000,7.000000C2.000000,17.299999 2.700000,18.000000 3.500000,18.000000C4.300000,18.000000 5.000000,17.299999 5.000000,16.500000l0.000000,-7.000000C5.000000,8.700000 4.300000,8.000000 3.500000,8.000000zM20.500000,8.000000C19.700001,8.000000 19.000000,8.700000 19.000000,9.500000l0.000000,7.000000c0.000000,0.800000 0.700000,1.500000 1.500000,1.500000c0.800000,0.000000 1.500000,-0.700000 1.500000,-1.500000l0.000000,-7.000000C22.000000,8.700000 21.299999,8.000000 20.500000,8.000000zM15.500000,2.200000l1.300000,-1.300000c0.200000,-0.200000 0.200000,-0.500000 0.000000,-0.700000c-0.200000,-0.200000 -0.500000,-0.200000 -0.700000,0.000000l-1.500000,1.500000C13.900000,1.200000 13.000000,1.000000 12.000000,1.000000c-1.000000,0.000000 -1.900000,0.200000 -2.700000,0.600000L7.900000,0.100000C7.700000,0.000000 7.300000,0.000000 7.100000,0.100000C7.000000,0.300000 7.000000,0.700000 7.100000,0.900000l1.300000,1.300000C7.000000,3.300000 6.000000,5.000000 6.000000,7.000000l12.000000,0.000000C18.000000,5.000000 17.000000,3.200000 15.500000,2.200000zM10.000000,5.000000L9.000000,5.000000L9.000000,4.000000l1.000000,0.000000L10.000000,5.000000zM15.000000,5.000000l-1.000000,0.000000L14.000000,4.000000l1.000000,0.000000L15.000000,5.000000z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_android.xml"
+ line="22"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1121 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M23.9998,10.667C16.6398,10.667 10.6665,16.6403 10.6665,24.0003C10.6665,31.3603 16.6398,37.3337 23.9998,37.3337C31.3598,37.3337 37.3332,31.3603 37.3332,24.0003C37.3332,16.6403 31.3598,10.667 23.9998,10.667ZM17.4265,32.3737C17.9998,31.1737 21.4932,30.0003 23.9998,30.0003C26.5065,30.0003 30.0132,31.1737 30.5732,32.3737C28.7598,33.8137 26.4798,34.667 23.9998,34.667C21.5198,34.667 19.2398,33.8137 17.4265,32.3737ZM23.9998,27.3337C25.9465,27.3337 30.5732,28.1203 32.4798,30.4403C33.8398,28.6537 34.6665,26.427 34.6665,24.0003C34.6665,18.1203 29.8798,13.3337 23.9998,13.3337C18.1198,13.3337 13.3332,18.1203 13.3332,24.0003C13.3332,26.427 14.1598,28.6537 15.5198,30.4403C17.4265,28.1203 22.0532,27.3337 23.9998,27.3337ZM23.9998,16.0003C21.4132,16.0003 19.3332,18.0803 19.3332,20.667C19.3332,23.2537 21.4132,25.3337 23.9998,25.3337C26.5865,25.3337 28.6665,23.2537 28.6665,20.667C28.6665,18.0803 26.5865,16.0003 23.9998,16.0003ZM21.9998,20.667C21.9998,21.7737 22.8932,22.667 23.9998,22.667C25.1065,22.667 25.9998,21.7737 25.9998,20.667C25.9998,19.5603 25.1065,18.667 23.9998,18.667C22.8932,18.667 21.9998,19.5603 21.9998,20.667Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_avatar_guest_user.xml"
+ line="23"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1055 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData=" M66.67 -27.59 C66.67,-27.59 66.67,-66.67 66.67,-66.67 C66.67,-66.67 27.59,-66.67 27.59,-66.67 C27.59,-66.67 0,-94.25 0,-94.25 C0,-94.25 -27.58,-66.67 -27.58,-66.67 C-27.58,-66.67 -66.66,-66.67 -66.66,-66.67 C-66.66,-66.67 -66.66,-27.59 -66.66,-27.59 C-66.66,-27.59 -94.25,0 -94.25,0 C-94.25,0 -66.66,27.58 -66.66,27.58 C-66.66,27.58 -66.66,66.66 -66.66,66.66 C-66.66,66.66 -27.58,66.66 -27.58,66.66 C-27.58,66.66 0,94.25 0,94.25 C0,94.25 27.59,66.66 27.59,66.66 C27.59,66.66 66.67,66.66 66.67,66.66 C66.67,66.66 66.67,27.58 66.67,27.58 C66.67,27.58 94.25,0 94.25,0 C94.25,0 66.67,-27.59 66.67,-27.59c M50 20.66 C50,20.66 50,50 50,50 C50,50 20.67,50 20.67,50 C20.67,50 0,70.66 0,70.66 C0,70.66 -20.66,50 -20.66,50 C-20.66,50 -50,50 -50,50 C-50,50 -50,20.66 -50,20.66 C-50,20.66 -70.66,0 -70.66,0 C-70.66,0 -50,-20.67 -50,-20.67 C-50,-20.67 -50,-50 -50,-50 C-50,-50 -20.66,-50 -20.66,-50 C-20.66,-50 0,-70.67 0,-70.67 C0,-70.67 20.67,-50 20.67,-50 C20.67,-50 50,-50 50,-50 C50,-50 50,-20.67 50,-20.67 C50,-20.67 70.67,0 70.67,0 C70.67,0 50,20.66 50,20.66c " />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_brightness_full.xml"
+ line="19"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1055 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData=" M66.67 -27.59 C66.67,-27.59 66.67,-66.67 66.67,-66.67 C66.67,-66.67 27.59,-66.67 27.59,-66.67 C27.59,-66.67 0,-94.25 0,-94.25 C0,-94.25 -27.58,-66.67 -27.58,-66.67 C-27.58,-66.67 -66.66,-66.67 -66.66,-66.67 C-66.66,-66.67 -66.66,-27.59 -66.66,-27.59 C-66.66,-27.59 -94.25,0 -94.25,0 C-94.25,0 -66.66,27.58 -66.66,27.58 C-66.66,27.58 -66.66,66.66 -66.66,66.66 C-66.66,66.66 -27.58,66.66 -27.58,66.66 C-27.58,66.66 0,94.25 0,94.25 C0,94.25 27.59,66.66 27.59,66.66 C27.59,66.66 66.67,66.66 66.67,66.66 C66.67,66.66 66.67,27.58 66.67,27.58 C66.67,27.58 94.25,0 94.25,0 C94.25,0 66.67,-27.59 66.67,-27.59c M50 20.66 C50,20.66 50,50 50,50 C50,50 20.67,50 20.67,50 C20.67,50 0,70.66 0,70.66 C0,70.66 -20.66,50 -20.66,50 C-20.66,50 -50,50 -50,50 C-50,50 -50,20.66 -50,20.66 C-50,20.66 -70.66,0 -70.66,0 C-70.66,0 -50,-20.67 -50,-20.67 C-50,-20.67 -50,-50 -50,-50 C-50,-50 -20.66,-50 -20.66,-50 C-20.66,-50 0,-70.67 0,-70.67 C0,-70.67 20.67,-50 20.67,-50 C20.67,-50 50,-50 50,-50 C50,-50 50,-20.67 50,-20.67 C50,-20.67 70.67,0 70.67,0 C70.67,0 50,20.66 50,20.66c " />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_brightness_low.xml"
+ line="19"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1054 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M66.67 -27.59 C66.67,-27.59 66.67,-66.67 66.67,-66.67 C66.67,-66.67 27.59,-66.67 27.59,-66.67 C27.59,-66.67 0,-94.25 0,-94.25 C0,-94.25 -27.58,-66.67 -27.58,-66.67 C-27.58,-66.67 -66.66,-66.67 -66.66,-66.67 C-66.66,-66.67 -66.66,-27.59 -66.66,-27.59 C-66.66,-27.59 -94.25,0 -94.25,0 C-94.25,0 -66.66,27.58 -66.66,27.58 C-66.66,27.58 -66.66,66.66 -66.66,66.66 C-66.66,66.66 -27.58,66.66 -27.58,66.66 C-27.58,66.66 0,94.25 0,94.25 C0,94.25 27.59,66.66 27.59,66.66 C27.59,66.66 66.67,66.66 66.67,66.66 C66.67,66.66 66.67,27.58 66.67,27.58 C66.67,27.58 94.25,0 94.25,0 C94.25,0 66.67,-27.59 66.67,-27.59c M50 20.66 C50,20.66 50,50 50,50 C50,50 20.67,50 20.67,50 C20.67,50 0,70.66 0,70.66 C0,70.66 -20.66,50 -20.66,50 C-20.66,50 -50,50 -50,50 C-50,50 -50,20.66 -50,20.66 C-50,20.66 -70.66,0 -70.66,0 C-70.66,0 -50,-20.67 -50,-20.67 C-50,-20.67 -50,-50 -50,-50 C-50,-50 -20.66,-50 -20.66,-50 C-20.66,-50 0,-70.67 0,-70.67 C0,-70.67 20.67,-50 20.67,-50 C20.67,-50 50,-50 50,-50 C50,-50 50,-20.67 50,-20.67 C50,-20.67 70.67,0 70.67,0 C70.67,0 50,20.66 50,20.66c " />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_brightness_medium.xml"
+ line="19"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (831 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M12,16Q13.875,16 15.188,14.688Q16.5,13.375 16.5,11.5Q16.5,9.625 15.188,8.312Q13.875,7 12,7Q10.125,7 8.812,8.312Q7.5,9.625 7.5,11.5Q7.5,13.375 8.812,14.688Q10.125,16 12,16ZM12,14.2Q10.875,14.2 10.088,13.412Q9.3,12.625 9.3,11.5Q9.3,10.375 10.088,9.587Q10.875,8.8 12,8.8Q13.125,8.8 13.913,9.587Q14.7,10.375 14.7,11.5Q14.7,12.625 13.913,13.412Q13.125,14.2 12,14.2ZM12,19Q8.35,19 5.35,16.962Q2.35,14.925 1,11.5Q2.35,8.075 5.35,6.037Q8.35,4 12,4Q15.65,4 18.65,6.037Q21.65,8.075 23,11.5Q21.65,14.925 18.65,16.962Q15.65,19 12,19ZM12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5Q12,11.5 12,11.5ZM12,17Q14.825,17 17.188,15.512Q19.55,14.025 20.8,11.5Q19.55,8.975 17.188,7.487Q14.825,6 12,6Q9.175,6 6.812,7.487Q4.45,8.975 3.2,11.5Q4.45,14.025 6.812,15.512Q9.175,17 12,17Z"/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_broadcast_code_eye.xml"
+ line="25"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1041 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M798,840Q673,840 551,785.5Q429,731 329,631Q229,531 174.5,409Q120,287 120,162Q120,144 132,132Q144,120 162,120L324,120Q338,120 349,129.5Q360,139 362,152L388,292Q390,308 387,319Q384,330 376,338L279,436Q299,473 326.5,507.5Q354,542 387,574Q418,605 452,631.5Q486,658 524,680L618,586Q627,577 641.5,572.5Q656,568 670,570L808,598Q822,602 831,612.5Q840,623 840,636L840,798Q840,816 828,828Q816,840 798,840ZM241,360L307,294Q307,294 307,294Q307,294 307,294L290,200Q290,200 290,200Q290,200 290,200L201,200Q201,200 201,200Q201,200 201,200Q206,241 215,281Q224,321 241,360ZM599,718Q638,735 678.5,745Q719,755 760,758Q760,758 760,758Q760,758 760,758L760,670Q760,670 760,670Q760,670 760,670L666,651Q666,651 666,651Q666,651 666,651L599,718ZM241,360Q241,360 241,360Q241,360 241,360Q241,360 241,360Q241,360 241,360L241,360Q241,360 241,360Q241,360 241,360L241,360Q241,360 241,360Q241,360 241,360L241,360ZM599,718L599,718Q599,718 599,718Q599,718 599,718L599,718Q599,718 599,718Q599,718 599,718L599,718Q599,718 599,718Q599,718 599,718Q599,718 599,718Q599,718 599,718Z"/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_call.xml"
+ line="25"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (902 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M15,9.683V7C15,6.7348 14.8946,6.4804 14.7071,6.2929C14.5196,6.1054 14.2652,6 14,6H10C9.7348,6 9.4804,6.1054 9.2929,6.2929C9.1053,6.4804 9,6.7348 9,7V9.683C7.855,10.2245 6.8787,11.067 6.1756,12.1205C5.4725,13.174 5.0689,14.3988 5.0081,15.6639C4.9473,16.929 5.2315,18.1868 5.8304,19.3029C6.4292,20.4189 7.3202,21.3512 8.408,22H15.592C16.6798,21.3512 17.5707,20.4189 18.1696,19.3029C18.7685,18.1868 19.0527,16.929 18.9919,15.6639C18.9311,14.3988 18.5275,13.174 17.8244,12.1205C17.1212,11.067 16.145,10.2245 15,9.683ZM14.989,20H9.011C8.3852,19.5381 7.877,18.9352 7.5276,18.2402C7.1783,17.5453 6.9975,16.7778 7,16C7.0041,15.0553 7.2746,14.131 7.7803,13.3331C8.286,12.5351 9.0065,11.896 9.859,11.489L11,10.946V8H13V10.946L14.141,11.489C14.9935,11.896 15.714,12.5351 16.2197,13.3331C16.7254,14.131 16.9959,15.0553 17,16C17.0025,16.7778 16.8217,17.5453 16.4723,18.2402C16.123,18.9352 15.6148,19.5381 14.989,20Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_air_freshener_off.xml"
+ line="41"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1852 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M18,2.01L6,2C5.7371,1.9991 5.4766,2.0502 5.2335,2.1504C4.9905,2.2506 4.7696,2.3979 4.5837,2.5838C4.3978,2.7696 4.2505,2.9905 4.1504,3.2335C4.0502,3.4766 3.9991,3.7371 4,4V20C3.9991,20.2629 4.0502,20.5234 4.1504,20.7665C4.2505,21.0096 4.3978,21.2304 4.5837,21.4163C4.7696,21.6022 4.9905,21.7494 5.2335,21.8496C5.4766,21.9498 5.7371,22.0009 6,22H18C18.2629,22.0009 18.5234,21.9498 18.7665,21.8496C19.0095,21.7494 19.2304,21.6022 19.4163,21.4163C19.6022,21.2304 19.7495,21.0096 19.8496,20.7665C19.9498,20.5234 20.0009,20.2629 20,20V4C20.0007,3.7376 19.9493,3.4778 19.8489,3.2354C19.7485,2.993 19.6011,2.7728 19.4151,2.5878C19.2291,2.4027 19.0083,2.2564 18.7654,2.1572C18.5225,2.0581 18.2624,2.008 18,2.01ZM11,5C11.1978,5 11.3911,5.0587 11.5556,5.1686C11.72,5.2785 11.8482,5.4346 11.9239,5.6173C11.9996,5.8 12.0194,6.0011 11.9808,6.1951C11.9422,6.3891 11.847,6.5673 11.7071,6.7072C11.5673,6.847 11.3891,6.9423 11.1951,6.9809C11.0011,7.0194 10.8,6.9995 10.6173,6.9238C10.4346,6.8481 10.2784,6.72 10.1685,6.5556C10.0586,6.3911 10,6.1978 10,6C10,5.7348 10.1054,5.4804 10.2929,5.2929C10.4804,5.1053 10.7348,5 11,5ZM7,6C7,5.8022 7.0587,5.6089 7.1685,5.4445C7.2784,5.28 7.4346,5.1519 7.6173,5.0762C7.8,5.0005 8.0011,4.9806 8.1951,5.0192C8.3891,5.0578 8.5673,5.153 8.7071,5.2929C8.847,5.4327 8.9422,5.611 8.9808,5.8049C9.0194,5.9989 8.9996,6.2 8.9239,6.3827C8.8482,6.5654 8.72,6.7215 8.5556,6.8314C8.3911,6.9413 8.1978,7 8,7C7.7348,7 7.4804,6.8947 7.2929,6.7072C7.1054,6.5196 7,6.2652 7,6ZM12,18C11.0032,18.008 10.0441,17.6198 9.3335,16.9207C8.623,16.2216 8.2192,15.2688 8.211,14.272C8.2109,13.7806 8.3092,13.2941 8.5,12.8412C8.6908,12.3883 8.9703,11.9782 9.322,11.635L12,9L14.678,11.635C15.0297,11.9782 15.3092,12.3883 15.5,12.8412C15.6908,13.2941 15.7891,13.7806 15.789,14.272C15.7808,15.2688 15.377,16.2216 14.6665,16.9207C13.9559,17.6198 12.9968,18.008 12,18Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_dishwasher_on.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (878 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M12,15C11.6044,15 11.2177,15.1174 10.8889,15.3372C10.56,15.5569 10.3036,15.8692 10.1522,16.2346C10.0009,16.6001 9.9613,17.0022 10.0384,17.3901C10.1156,17.7781 10.3061,18.1346 10.5858,18.4143C10.8655,18.694 11.2219,18.8845 11.6098,18.9617C11.9978,19.0388 12.3999,18.999 12.7654,18.8477C13.1308,18.6963 13.4432,18.44 13.6629,18.1111C13.8827,17.7822 14,17.3956 14,17C14,16.4696 13.7893,15.9608 13.4142,15.5857C13.0391,15.2106 12.5304,15 12,15ZM12,18C11.8022,18 11.6089,17.9414 11.4444,17.8315C11.28,17.7217 11.1518,17.5653 11.0761,17.3826C11.0004,17.1998 10.9806,16.9989 11.0192,16.8049C11.0578,16.611 11.153,16.4328 11.2929,16.293C11.4327,16.1531 11.6109,16.0579 11.8049,16.0193C11.9989,15.9807 12.2,16.0005 12.3827,16.0762C12.5654,16.1519 12.7216,16.2799 12.8315,16.4443C12.9413,16.6088 13,16.8022 13,17C13,17.2652 12.8946,17.5195 12.7071,17.707C12.5196,17.8946 12.2652,18 12,18Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_doorbell_off.xml"
+ line="26"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1266 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M17,2H7C6.4696,2 5.9609,2.2106 5.5858,2.5857C5.2107,2.9608 5,3.4696 5,4V20C5,20.5304 5.2107,21.0392 5.5858,21.4143C5.9609,21.7894 6.4696,22 7,22H17C17.5304,22 18.0391,21.7894 18.4142,21.4143C18.7893,21.0392 19,20.5304 19,20V4C19,3.4696 18.7893,2.9608 18.4142,2.5857C18.0391,2.2106 17.5304,2 17,2ZM12,19C11.6044,19 11.2178,18.8826 10.8889,18.6628C10.56,18.4431 10.3036,18.1308 10.1522,17.7654C10.0009,17.3999 9.9613,16.9978 10.0384,16.6099C10.1156,16.2219 10.3061,15.8654 10.5858,15.5857C10.8655,15.306 11.2219,15.1155 11.6098,15.0383C11.9978,14.9612 12.3999,15.001 12.7654,15.1523C13.1308,15.3037 13.4432,15.56 13.6629,15.8889C13.8827,16.2178 14,16.6044 14,17C14,17.5304 13.7893,18.0392 13.4142,18.4143C13.0391,18.7894 12.5304,19 12,19ZM11,12.5H13C13,12.7652 12.8946,13.0195 12.7071,13.207C12.5196,13.3946 12.2652,13.5 12,13.5C11.7348,13.5 11.4804,13.3946 11.2929,13.207C11.1054,13.0195 11,12.7652 11,12.5ZM16,12H8V11H9V8.6599C8.9488,7.9537 9.1455,7.2519 9.5562,6.675C9.9669,6.0982 10.5659,5.6827 11.25,5.5V5.25C11.25,5.0511 11.329,4.8604 11.4697,4.7197C11.6103,4.5791 11.8011,4.5 12,4.5C12.1989,4.5 12.3897,4.5791 12.5303,4.7197C12.671,4.8604 12.75,5.0511 12.75,5.25V5.5C13.4351,5.6809 14.0352,6.0961 14.4462,6.6733C14.8572,7.2506 15.0532,7.9533 15,8.6599V11H16V12Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_doorbell_on.xml"
+ line="26"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (3845 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M16.345,8.3611L14.055,9.1791C13.8731,9.0458 13.6785,8.9309 13.474,8.8361C13.6398,7.9956 14.1302,7.2543 14.839,6.7731C15.3079,6.465 15.6646,6.0136 15.8558,5.4861C16.047,4.9587 16.0625,4.3836 15.8999,3.8466C15.7374,3.3097 15.4055,2.8397 14.9538,2.5069C14.5022,2.1741 13.955,1.9963 13.394,2.0001C8.994,2.0001 7.157,5.0071 8.361,7.6551L9.179,9.9451C9.0458,10.1269 8.9309,10.3215 8.836,10.5261C7.9954,10.3606 7.254,9.8701 6.773,9.1611C6.465,8.6922 6.0135,8.3355 5.4861,8.1443C4.9587,7.9531 4.3835,7.9375 3.8466,8.1001C3.3096,8.2627 2.8396,8.5946 2.5068,9.0462C2.174,9.4979 1.9962,10.0451 2,10.6061C2,15.0061 5.007,16.843 7.655,15.639L9.945,14.821C10.1267,14.9541 10.3209,15.069 10.525,15.1641C10.3598,16.0048 9.8692,16.7463 9.16,17.227C8.691,17.5351 8.3343,17.9867 8.1431,18.5142C7.9519,19.0418 7.9365,19.617 8.0992,20.154C8.2619,20.691 8.5939,21.161 9.0457,21.4937C9.4976,21.8264 10.0449,22.004 10.606,22.0001C15.006,22.0001 16.843,18.993 15.639,16.345L14.821,14.0551C14.954,13.8734 15.0689,13.6791 15.164,13.475C16.0048,13.6402 16.7462,14.1309 17.227,14.8401C17.5351,15.3091 17.9866,15.6657 18.5141,15.8569C19.0417,16.0481 19.6169,16.0636 20.1539,15.9009C20.6909,15.7382 21.1609,15.4061 21.4936,14.9543C21.8264,14.5025 22.004,13.9551 22,13.394C22,9 18.993,7.1571 16.345,8.3611ZM12,13.5001C11.7033,13.5001 11.4133,13.4121 11.1666,13.2473C10.92,13.0824 10.7277,12.8482 10.6142,12.5741C10.5006,12.3 10.4709,11.9984 10.5288,11.7074C10.5867,11.4164 10.7296,11.1492 10.9393,10.9394C11.1491,10.7296 11.4164,10.5867 11.7074,10.5289C11.9983,10.471 12.2999,10.5007 12.574,10.6143C12.8481,10.7278 13.0824,10.92 13.2472,11.1667C13.412,11.4134 13.5,11.7034 13.5,12.0001C13.5,12.3979 13.342,12.7794 13.0607,13.0607C12.7793,13.342 12.3978,13.5001 12,13.5001ZM10.245,5.2161C10.6327,4.7742 11.1217,4.4328 11.6701,4.2211C12.2184,4.0093 12.8099,3.9335 13.394,4.0001C13.5259,3.9959 13.6555,4.0354 13.7627,4.1124C13.8699,4.1893 13.9487,4.2995 13.987,4.4258C14.0253,4.5521 14.0208,4.6875 13.9744,4.811C13.9279,4.9346 13.842,5.0393 13.73,5.1091C13.1418,5.5017 12.6392,6.0092 12.2521,6.601C11.8651,7.1929 11.6018,7.8568 11.478,8.553C11.2666,8.5847 11.0587,8.6362 10.857,8.707L10.181,6.8271C10.0515,6.576 9.9893,6.2955 10.0005,6.0131C10.0117,5.7308 10.0959,5.4561 10.245,5.2161ZM6.827,13.816C6.576,13.9458 6.2956,14.0083 6.0132,13.9973C5.7308,13.9862 5.4561,13.902 5.216,13.753C4.7745,13.3655 4.4332,12.8769 4.2215,12.3289C4.0098,11.7809 3.9338,11.1898 4,10.6061C3.9959,10.4742 4.0353,10.3446 4.1123,10.2374C4.1893,10.1302 4.2994,10.0513 4.4257,10.0131C4.552,9.9748 4.6874,9.9792 4.8109,10.0257C4.9345,10.0722 5.0392,10.1581 5.109,10.2701C5.5015,10.8581 6.0088,11.3607 6.6005,11.7477C7.1922,12.1347 7.8559,12.3981 8.552,12.522C8.5844,12.7334 8.6363,12.9413 8.707,13.1431L6.827,13.816ZM13.755,18.782C13.3675,19.2242 12.8786,19.566 12.3302,19.7781C11.7818,19.9902 11.1902,20.0664 10.606,20.0001C10.4741,20.0042 10.3445,19.9647 10.2373,19.8878C10.1301,19.8108 10.0512,19.7006 10.013,19.5743C9.9747,19.448 9.9791,19.3126 10.0256,19.1891C10.0721,19.0656 10.158,18.9608 10.27,18.8911C10.8581,18.4987 11.3606,17.9914 11.7475,17.3997C12.1343,16.808 12.3974,16.1441 12.521,15.4481C12.7327,15.4156 12.9409,15.3638 13.143,15.2931L13.818,17.173C13.9477,17.4241 14.0101,17.7045 13.999,17.9869C13.988,18.2692 13.9039,18.5439 13.755,18.7841V18.782ZM18.891,13.7281C18.4985,13.1399 17.991,12.6373 17.3992,12.2504C16.8073,11.8636 16.1432,11.6005 15.447,11.477C15.4154,11.2653 15.3639,11.057 15.293,10.855L17.173,10.1801C17.424,10.0503 17.7044,9.9879 17.9868,9.9989C18.2692,10.0099 18.5439,10.094 18.784,10.243C19.2261,10.631 19.5677,11.1202 19.7795,11.669C19.9912,12.2178 20.0669,12.8097 20,13.394C20.0041,13.5259 19.9647,13.6555 19.8877,13.7628C19.8107,13.87 19.7006,13.9488 19.5743,13.9871C19.448,14.0253 19.3126,14.0209 19.1891,13.9744C19.0655,13.928 18.9608,13.8421 18.891,13.73V13.7281Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_fan_off.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1740 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M16.345,8.3611L14.055,9.1791C13.8731,9.0458 13.6785,8.9309 13.474,8.8361C13.6398,7.9956 14.1302,7.2543 14.839,6.7731C15.3079,6.465 15.6646,6.0136 15.8558,5.4861C16.047,4.9587 16.0625,4.3836 15.8999,3.8466C15.7374,3.3097 15.4055,2.8397 14.9538,2.5069C14.5022,2.1741 13.955,1.9963 13.394,2.0001C8.994,2.0001 7.157,5.0071 8.361,7.6551L9.179,9.9451C9.0457,10.1269 8.9309,10.3215 8.836,10.5261C7.9954,10.3606 7.254,9.8701 6.773,9.1611C6.465,8.6922 6.0135,8.3355 5.4861,8.1443C4.9587,7.9531 4.3835,7.9375 3.8466,8.1001C3.3096,8.2627 2.8396,8.5946 2.5068,9.0462C2.174,9.4979 1.9962,10.0451 2,10.6061C2,15.0061 5.007,16.843 7.655,15.639L9.945,14.821C10.1267,14.9541 10.3209,15.069 10.525,15.1641C10.3598,16.0048 9.8692,16.7463 9.16,17.227C8.691,17.5351 8.3343,17.9867 8.1431,18.5142C7.9519,19.0418 7.9365,19.617 8.0992,20.154C8.2619,20.691 8.5939,21.161 9.0457,21.4937C9.4976,21.8264 10.0449,22.004 10.606,22.0001C15.006,22.0001 16.843,18.993 15.639,16.345L14.821,14.0551C14.954,13.8734 15.0689,13.6791 15.164,13.475C16.0048,13.6402 16.7462,14.1309 17.227,14.8401C17.5351,15.3091 17.9866,15.6657 18.5141,15.8569C19.0417,16.0481 19.6169,16.0636 20.1539,15.9009C20.6909,15.7382 21.1609,15.4061 21.4936,14.9543C21.8264,14.5025 22.004,13.9551 22,13.394C22,9 18.993,7.1571 16.345,8.3611ZM12,13.5001C11.7033,13.5001 11.4133,13.4121 11.1666,13.2473C10.92,13.0824 10.7277,12.8482 10.6142,12.5741C10.5006,12.3 10.4709,11.9984 10.5288,11.7074C10.5867,11.4164 10.7296,11.1492 10.9393,10.9394C11.1491,10.7296 11.4164,10.5867 11.7074,10.5289C11.9983,10.471 12.2999,10.5007 12.574,10.6143C12.8481,10.7278 13.0824,10.92 13.2472,11.1667C13.412,11.4134 13.5,11.7034 13.5,12.0001C13.5,12.3979 13.342,12.7794 13.0607,13.0607C12.7794,13.342 12.3978,13.5001 12,13.5001Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_fan_on.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1072 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M18,8H17V6C17,4.6739 16.4732,3.402 15.5355,2.4644C14.5979,1.5267 13.3261,1 12,1C10.6739,1 9.4022,1.5267 8.4645,2.4644C7.5268,3.402 7,4.6739 7,6V8H6C5.47,8.0016 4.9623,8.2127 4.5875,8.5874C4.2128,8.9621 4.0016,9.47 4,10V20C4.0016,20.5299 4.2128,21.0379 4.5875,21.4126C4.9623,21.7873 5.47,21.9984 6,22H18C18.5299,21.9984 19.0377,21.7873 19.4125,21.4126C19.7872,21.0379 19.9984,20.5299 20,20V10C19.9984,9.47 19.7872,8.9621 19.4125,8.5874C19.0377,8.2127 18.5299,8.0016 18,8ZM12,17C11.6044,17 11.2178,16.8828 10.8889,16.6631C10.56,16.4433 10.3036,16.1306 10.1522,15.7651C10.0009,15.3997 9.9613,14.9978 10.0384,14.6099C10.1156,14.2219 10.3061,13.8656 10.5858,13.5859C10.8655,13.3062 11.2219,13.1157 11.6098,13.0386C11.9978,12.9614 12.3999,13.001 12.7654,13.1523C13.1308,13.3037 13.4432,13.5598 13.6629,13.8887C13.8827,14.2176 14,14.6044 14,15C13.9984,15.5299 13.7872,16.0379 13.4125,16.4126C13.0377,16.7873 12.5299,16.9984 12,17ZM15,8H9V6C9,5.2043 9.3161,4.4415 9.8787,3.8789C10.4413,3.3163 11.2044,3 12,3C12.7956,3 13.5587,3.3163 14.1213,3.8789C14.6839,4.4415 15,5.2043 15,6V8Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_lock_on.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1585 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M20,4H4C3.4696,4 2.9609,4.2107 2.5858,4.5858C2.2107,4.9609 2,5.4696 2,6V18C2,18.5304 2.2107,19.0391 2.5858,19.4142C2.9609,19.7893 3.4696,20 4,20H20C20.5304,20 21.0391,19.7893 21.4142,19.4142C21.7893,19.0391 22,18.5304 22,18V6C22,5.4696 21.7893,4.9609 21.4142,4.5858C21.0391,4.2107 20.5304,4 20,4ZM15,17H5V7H15V17ZM18,17C17.8022,17 17.6089,16.9413 17.4444,16.8314C17.28,16.7215 17.1518,16.5654 17.0761,16.3827C17.0004,16.2 16.9806,15.9989 17.0192,15.8049C17.0578,15.611 17.153,15.4327 17.2929,15.2928C17.4327,15.153 17.6109,15.0578 17.8049,15.0192C17.9989,14.9806 18.2,15.0005 18.3827,15.0762C18.5654,15.1519 18.7216,15.28 18.8315,15.4445C18.9414,15.6089 19,15.8022 19,16C19,16.2652 18.8946,16.5196 18.7071,16.7072C18.5196,16.8947 18.2652,17 18,17ZM18,13C17.8022,13 17.6089,12.9413 17.4444,12.8314C17.28,12.7215 17.1518,12.5654 17.0761,12.3827C17.0004,12.2 16.9806,11.9989 17.0192,11.8049C17.0578,11.611 17.153,11.4327 17.2929,11.2928C17.4327,11.153 17.6109,11.0578 17.8049,11.0192C17.9989,10.9806 18.2,11.0005 18.3827,11.0762C18.5654,11.1519 18.7216,11.28 18.8315,11.4445C18.9414,11.6089 19,11.8022 19,12C19,12.2652 18.8946,12.5196 18.7071,12.7072C18.5196,12.8947 18.2652,13 18,13ZM18,9C17.8022,9 17.6089,8.9413 17.4444,8.8314C17.28,8.7215 17.1518,8.5654 17.0761,8.3827C17.0004,8.2 16.9806,7.9989 17.0192,7.8049C17.0578,7.6109 17.153,7.4327 17.2929,7.2929C17.4327,7.153 17.6109,7.0578 17.8049,7.0192C17.9989,6.9806 18.2,7.0005 18.3827,7.0762C18.5654,7.1519 18.7216,7.28 18.8315,7.4445C18.9414,7.6089 19,7.8022 19,8C19,8.2652 18.8946,8.5196 18.7071,8.7072C18.5196,8.8947 18.2652,9 18,9Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_microwave_on.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1375 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M22.379,20.515L21,15V13C21,12.4696 20.7893,11.9609 20.4142,11.5858C20.0391,11.2107 19.5304,11 19,11H15V4C15,3.2043 14.6839,2.4413 14.1213,1.8787C13.5587,1.3161 12.7956,1 12,1C11.2043,1 10.4413,1.3161 9.8786,1.8787C9.316,2.4413 9,3.2043 9,4V11H5C4.4695,11 3.9608,11.2107 3.5858,11.5858C3.2107,11.9609 3,12.4696 3,13V15L1.621,20.515C1.5473,20.8099 1.5417,21.1178 1.6048,21.4151C1.6679,21.7125 1.798,21.9916 1.9851,22.2311C2.1722,22.4707 2.4115,22.6645 2.6847,22.7977C2.958,22.9309 3.258,23.0001 3.562,23H20.438C20.742,23.0001 21.042,22.9309 21.3152,22.7977C21.5884,22.6645 21.8277,22.4707 22.0149,22.2311C22.202,21.9916 22.332,21.7125 22.3951,21.4151C22.4582,21.1178 22.4527,20.8099 22.379,20.515ZM11,4C11,3.7348 11.1053,3.4804 11.2929,3.2929C11.4804,3.1054 11.7348,3 12,3C12.2652,3 12.5195,3.1054 12.7071,3.2929C12.8946,3.4804 13,3.7348 13,4V11H11V4ZM5,13H19V15H5V13ZM18,21V19C18,18.7348 17.8946,18.4804 17.7071,18.2929C17.5195,18.1054 17.2652,18 17,18C16.7348,18 16.4804,18.1054 16.2929,18.2929C16.1053,18.4804 16,18.7348 16,19V21H13V19C13,18.7348 12.8946,18.4804 12.7071,18.2929C12.5195,18.1054 12.2652,18 12,18C11.7348,18 11.4804,18.1054 11.2929,18.2929C11.1053,18.4804 11,18.7348 11,19V21H8V19C8,18.7348 7.8946,18.4804 7.7071,18.2929C7.5195,18.1054 7.2652,18 7,18C6.7348,18 6.4804,18.1054 6.2929,18.2929C6.1053,18.4804 6,18.7348 6,19V21H3.562L4.562,17H19.438L20.438,21H18Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_mop_off.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1204 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M22.379,20.515L21,15V13C21,12.4696 20.7893,11.9609 20.4142,11.5858C20.0391,11.2107 19.5304,11 19,11H15V4C15,3.2043 14.6839,2.4413 14.1213,1.8787C13.5587,1.3161 12.7956,1 12,1C11.2043,1 10.4413,1.3161 9.8787,1.8787C9.316,2.4413 9,3.2043 9,4V11H5C4.4695,11 3.9608,11.2107 3.5858,11.5858C3.2107,11.9609 3,12.4696 3,13V15L1.621,20.515C1.5473,20.8099 1.5417,21.1178 1.6048,21.4151C1.6679,21.7125 1.798,21.9916 1.9851,22.2311C2.1722,22.4707 2.4115,22.6645 2.6847,22.7977C2.958,22.9309 3.258,23.0001 3.562,23H20.438C20.742,23.0001 21.042,22.9309 21.3152,22.7977C21.5885,22.6645 21.8277,22.4707 22.0148,22.2311C22.202,21.9916 22.332,21.7125 22.3951,21.4151C22.4582,21.1178 22.4527,20.8099 22.379,20.515ZM18,21V19C18,18.7348 17.8946,18.4804 17.7071,18.2929C17.5195,18.1054 17.2652,18 17,18C16.7348,18 16.4804,18.1054 16.2929,18.2929C16.1053,18.4804 16,18.7348 16,19V21H13V19C13,18.7348 12.8946,18.4804 12.7071,18.2929C12.5195,18.1054 12.2652,18 12,18C11.7348,18 11.4804,18.1054 11.2929,18.2929C11.1053,18.4804 11,18.7348 11,19V21H8V19C8,18.7348 7.8946,18.4804 7.7071,18.2929C7.5195,18.1054 7.2652,18 7,18C6.7348,18 6.4804,18.1054 6.2929,18.2929C6.1053,18.4804 6,18.7348 6,19V21H3.562L4.562,17H19.438L20.438,21H18Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_mop_on.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1592 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M17,12C17,12.5304 16.7893,13.0391 16.4142,13.4142C16.0391,13.7893 15.5304,14 15,14H9C8.4696,14 7.9609,13.7893 7.5858,13.4142C7.2107,13.0391 7,12.5304 7,12V10H3V19C3,19.5304 3.2107,20.0391 3.5858,20.4142C3.9609,20.7893 4.4696,21 5,21H19C19.5304,21 20.0391,20.7893 20.4142,20.4142C20.7893,20.0391 21,19.5304 21,19V10H17V12ZM8,18C7.8022,18 7.6089,17.9413 7.4444,17.8314C7.28,17.7215 7.1518,17.5654 7.0761,17.3827C7.0004,17.2 6.9806,16.9989 7.0192,16.8049C7.0578,16.611 7.153,16.4327 7.2929,16.2928C7.4328,16.153 7.6109,16.0578 7.8049,16.0192C7.9989,15.9806 8.2,16.0005 8.3827,16.0762C8.5654,16.1519 8.7216,16.28 8.8315,16.4445C8.9413,16.6089 9,16.8022 9,17C9,17.2652 8.8946,17.5196 8.7071,17.7072C8.5196,17.8947 8.2652,18 8,18ZM12,18C11.8022,18 11.6089,17.9413 11.4444,17.8314C11.28,17.7215 11.1518,17.5654 11.0761,17.3827C11.0004,17.2 10.9806,16.9989 11.0192,16.8049C11.0578,16.611 11.153,16.4327 11.2929,16.2928C11.4327,16.153 11.6109,16.0578 11.8049,16.0192C11.9989,15.9806 12.2,16.0005 12.3827,16.0762C12.5654,16.1519 12.7216,16.28 12.8315,16.4445C12.9414,16.6089 13,16.8022 13,17C13,17.2652 12.8946,17.5196 12.7071,17.7072C12.5196,17.8947 12.2652,18 12,18ZM16,18C15.8022,18 15.6089,17.9413 15.4444,17.8314C15.28,17.7215 15.1518,17.5654 15.0761,17.3827C15.0004,17.2 14.9806,16.9989 15.0192,16.8049C15.0578,16.611 15.153,16.4327 15.2929,16.2928C15.4327,16.153 15.6109,16.0578 15.8049,16.0192C15.9989,15.9806 16.2,16.0005 16.3827,16.0762C16.5654,16.1519 16.7216,16.28 16.8315,16.4445C16.9414,16.6089 17,16.8022 17,17C17,17.2652 16.8946,17.5196 16.7071,17.7072C16.5196,17.8947 16.2652,18 16,18Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_multicooker_on.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (829 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M12,2C10.0222,2 8.0888,2.5865 6.4443,3.6853C4.7998,4.7841 3.5181,6.346 2.7612,8.1732C2.0043,10.0005 1.8063,12.0111 2.1922,13.9509C2.578,15.8907 3.5304,17.6725 4.9289,19.071C6.3275,20.4696 8.1093,21.422 10.0491,21.8079C11.9889,22.1937 13.9996,21.9956 15.8268,21.2388C17.6541,20.4819 19.2159,19.2002 20.3147,17.5557C21.4135,15.9112 22,13.9778 22,12C22,9.3478 20.9464,6.8043 19.0711,4.929C17.1957,3.0536 14.6522,2 12,2ZM12,20C10.4178,20 8.871,19.5308 7.5554,18.6517C6.2399,17.7727 5.2145,16.5233 4.609,15.0615C4.0035,13.5997 3.845,11.9912 4.1537,10.4393C4.4624,8.8875 5.2243,7.462 6.3432,6.3431C7.462,5.2243 8.8874,4.4624 10.4393,4.1537C11.9911,3.845 13.5997,4.0035 15.0615,4.609C16.5233,5.2145 17.7727,6.2398 18.6518,7.5554C19.5308,8.871 20,10.4177 20,12C20,14.1217 19.1572,16.1566 17.6569,17.6569C16.1566,19.1572 14.1217,20 12,20Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_outlet_off.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (814 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M12,10C12.5933,10 13.1734,9.824 13.6667,9.4944C14.1601,9.1648 14.5446,8.6963 14.7716,8.1481C14.9987,7.5999 15.0581,6.9966 14.9424,6.4147C14.8266,5.8327 14.5409,5.2982 14.1213,4.8787C13.7018,4.4591 13.1672,4.1734 12.5853,4.0576C12.0033,3.9419 11.4001,4.0013 10.8519,4.2284C10.3038,4.4555 9.8352,4.8399 9.5056,5.3333C9.1759,5.8266 9,6.4067 9,7C9,7.7957 9.3161,8.5587 9.8787,9.1214C10.4413,9.684 11.2044,10 12,10ZM12,6C12.1978,6 12.3911,6.0587 12.5556,6.1686C12.72,6.2785 12.8482,6.4346 12.9239,6.6173C12.9996,6.8 13.0194,7.0011 12.9808,7.1951C12.9422,7.3891 12.847,7.5673 12.7071,7.7072C12.5673,7.847 12.3891,7.9423 12.1951,7.9809C12.0011,8.0194 11.8,7.9995 11.6173,7.9238C11.4346,7.8481 11.2784,7.72 11.1685,7.5556C11.0587,7.3911 11,7.1978 11,7C11,6.7348 11.1054,6.4804 11.2929,6.2929C11.4804,6.1053 11.7348,6 12,6Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_remote_control_off.xml"
+ line="26"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (3261 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M16,1H8C7.4696,1 6.9609,1.2107 6.5858,1.5858C6.2107,1.9609 6,2.4696 6,3V21C6,21.5304 6.2107,22.0391 6.5858,22.4142C6.9609,22.7893 7.4696,23 8,23H16C16.5304,23 17.0391,22.7893 17.4142,22.4142C17.7893,22.0391 18,21.5304 18,21V3C18,2.4696 17.7893,1.9609 17.4142,1.5858C17.0391,1.2107 16.5304,1 16,1ZM10,20C9.8022,20 9.6089,19.9413 9.4444,19.8314C9.28,19.7215 9.1518,19.5654 9.0761,19.3827C9.0004,19.2 8.9806,18.9989 9.0192,18.8049C9.0578,18.611 9.153,18.4327 9.2929,18.2928C9.4327,18.153 9.6109,18.0578 9.8049,18.0192C9.9989,17.9806 10.2,18.0005 10.3827,18.0762C10.5654,18.1519 10.7216,18.28 10.8315,18.4445C10.9414,18.6089 11,18.8022 11,19C11,19.2652 10.8946,19.5196 10.7071,19.7072C10.5196,19.8947 10.2652,20 10,20ZM10,17C9.8022,17 9.6089,16.9413 9.4444,16.8314C9.28,16.7215 9.1518,16.5654 9.0761,16.3827C9.0004,16.2 8.9806,15.9989 9.0192,15.8049C9.0578,15.611 9.153,15.4327 9.2929,15.2928C9.4327,15.153 9.6109,15.0578 9.8049,15.0192C9.9989,14.9806 10.2,15.0005 10.3827,15.0762C10.5654,15.1519 10.7216,15.28 10.8315,15.4445C10.9414,15.6089 11,15.8022 11,16C11,16.2652 10.8946,16.5196 10.7071,16.7072C10.5196,16.8947 10.2652,17 10,17ZM10,14C9.8022,14 9.6089,13.9413 9.4444,13.8314C9.28,13.7215 9.1518,13.5654 9.0761,13.3827C9.0004,13.2 8.9806,12.9989 9.0192,12.8049C9.0578,12.611 9.153,12.4327 9.2929,12.2928C9.4327,12.153 9.6109,12.0578 9.8049,12.0192C9.9989,11.9806 10.2,12.0005 10.3827,12.0762C10.5654,12.1519 10.7216,12.28 10.8315,12.4445C10.9414,12.6089 11,12.8022 11,13C11,13.2652 10.8946,13.5196 10.7071,13.7072C10.5196,13.8947 10.2652,14 10,14ZM14,20C13.8022,20 13.6089,19.9413 13.4444,19.8314C13.28,19.7215 13.1518,19.5654 13.0761,19.3827C13.0004,19.2 12.9806,18.9989 13.0192,18.8049C13.0578,18.611 13.153,18.4327 13.2929,18.2928C13.4327,18.153 13.6109,18.0578 13.8049,18.0192C13.9989,17.9806 14.2,18.0005 14.3827,18.0762C14.5654,18.1519 14.7216,18.28 14.8315,18.4445C14.9414,18.6089 15,18.8022 15,19C15,19.2652 14.8946,19.5196 14.7071,19.7072C14.5196,19.8947 14.2652,20 14,20ZM14,17C13.8022,17 13.6089,16.9413 13.4444,16.8314C13.28,16.7215 13.1518,16.5654 13.0761,16.3827C13.0004,16.2 12.9806,15.9989 13.0192,15.8049C13.0578,15.611 13.153,15.4327 13.2929,15.2928C13.4327,15.153 13.6109,15.0578 13.8049,15.0192C13.9989,14.9806 14.2,15.0005 14.3827,15.0762C14.5654,15.1519 14.7216,15.28 14.8315,15.4445C14.9414,15.6089 15,15.8022 15,16C15,16.2652 14.8946,16.5196 14.7071,16.7072C14.5196,16.8947 14.2652,17 14,17ZM14,14C13.8022,14 13.6089,13.9413 13.4444,13.8314C13.28,13.7215 13.1518,13.5654 13.0761,13.3827C13.0004,13.2 12.9806,12.9989 13.0192,12.8049C13.0578,12.611 13.153,12.4327 13.2929,12.2928C13.4327,12.153 13.6109,12.0578 13.8049,12.0192C13.9989,11.9806 14.2,12.0005 14.3827,12.0762C14.5654,12.1519 14.7216,12.28 14.8315,12.4445C14.9414,12.6089 15,12.8022 15,13C15,13.2652 14.8946,13.5196 14.7071,13.7072C14.5196,13.8947 14.2652,14 14,14ZM12,10C11.4067,10 10.8266,9.824 10.3333,9.4944C9.8399,9.1647 9.4554,8.6962 9.2284,8.1481C9.0013,7.5999 8.9419,6.9966 9.0576,6.4147C9.1734,5.8327 9.4591,5.2982 9.8787,4.8787C10.2982,4.4591 10.8328,4.1734 11.4147,4.0576C11.9967,3.9419 12.5999,4.0013 13.1481,4.2284C13.6962,4.4555 14.1648,4.8399 14.4944,5.3333C14.8241,5.8266 15,6.4067 15,7C15,7.7957 14.6839,8.5587 14.1213,9.1213C13.5587,9.684 12.7956,10 12,10Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_remote_control_on.xml"
+ line="26"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (909 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M2,7V17H22V7H2ZM11,13H5V11H11V13ZM14,13C13.8022,13 13.6089,12.9414 13.4444,12.8315C13.28,12.7217 13.1518,12.5653 13.0761,12.3826C13.0004,12.1998 12.9806,11.9989 13.0192,11.8049C13.0578,11.611 13.153,11.4328 13.2929,11.293C13.4327,11.1531 13.6109,11.0579 13.8049,11.0193C13.9989,10.9807 14.2,11.0005 14.3827,11.0762C14.5654,11.1519 14.7216,11.2799 14.8315,11.4443C14.9414,11.6088 15,11.8022 15,12C15,12.2652 14.8946,12.5195 14.7071,12.707C14.5196,12.8946 14.2652,13 14,13ZM17,13C16.8022,13 16.6089,12.9414 16.4444,12.8315C16.28,12.7217 16.1518,12.5653 16.0761,12.3826C16.0004,12.1998 15.9806,11.9989 16.0192,11.8049C16.0578,11.611 16.153,11.4328 16.2929,11.293C16.4327,11.1531 16.6109,11.0579 16.8049,11.0193C16.9989,10.9807 17.2,11.0005 17.3827,11.0762C17.5654,11.1519 17.7216,11.2799 17.8315,11.4443C17.9414,11.6088 18,11.8022 18,12C18,12.2652 17.8946,12.5195 17.7071,12.707C17.5196,12.8946 17.2652,13 17,13Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_set_top_on.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1931 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M19.56,11.361L13,8.4408V6.9999C13,6.7347 12.8946,6.4804 12.7071,6.2929C12.5196,6.1054 12.2652,5.9999 12,5.9999C11.8022,5.9999 11.6089,5.9413 11.4444,5.8315C11.28,5.7216 11.1518,5.5652 11.0761,5.3825C11.0004,5.1998 10.9806,4.9988 11.0192,4.8049C11.0578,4.6109 11.153,4.4327 11.2929,4.2929C11.4327,4.153 11.6109,4.0578 11.8049,4.0192C11.9989,3.9806 12.2,4.0004 12.3827,4.0761C12.5654,4.1518 12.7216,4.2798 12.8315,4.4443C12.9414,4.6087 13,4.8021 13,4.9999H15C15.0015,4.4496 14.8517,3.9095 14.5668,3.4386C14.2819,2.9678 13.8729,2.5843 13.3847,2.3303C12.8965,2.0762 12.3478,1.9613 11.7987,1.9982C11.2496,2.0351 10.7212,2.2224 10.2714,2.5395C9.8216,2.8566 9.4677,3.2915 9.2484,3.7963C9.0291,4.3011 8.9529,4.8563 9.0282,5.4015C9.1034,5.9467 9.3272,6.4608 9.6749,6.8874C10.0227,7.3139 10.4811,7.6365 11,7.82V8.4499L4.44,11.37C4.0115,11.5562 3.6468,11.8636 3.3909,12.2546C3.1351,12.6455 2.9992,13.1028 3,13.57V13.58C2.9995,13.8979 3.0617,14.2129 3.1831,14.5068C3.3046,14.8006 3.4828,15.0676 3.7076,15.2924C3.9325,15.5172 4.1994,15.6954 4.4933,15.8168C4.7871,15.9382 5.1021,16.0004 5.42,15.9999H7V21.9999H17V15.9999H18.58C18.898,16.0004 19.2129,15.9382 19.5067,15.8168C19.8006,15.6954 20.0676,15.5172 20.2924,15.2924C20.5172,15.0676 20.6954,14.8006 20.8169,14.5068C20.9383,14.2129 21.0005,13.8979 21,13.58V13.57C20.9994,13.1019 20.8631,12.644 20.6075,12.2519C20.3519,11.8598 19.988,11.5504 19.56,11.361ZM15,19.9999H9V14.9999H15V19.9999ZM18.58,13.9999H17V12.9999H7V13.9999H5.42C5.3642,13.9993 5.3091,13.9877 5.2577,13.9657C5.2064,13.9438 5.1599,13.9119 5.1209,13.872C5.0819,13.8321 5.0512,13.7846 5.0304,13.7328C5.0097,13.681 4.9993,13.6258 5,13.57C4.999,13.4889 5.0222,13.4094 5.0668,13.3417C5.1114,13.274 5.1752,13.221 5.25,13.1899L12,10.1899L18.75,13.1899C18.8245,13.2243 18.8876,13.2795 18.9319,13.3486C18.9761,13.4176 18.9998,13.4979 19,13.58C18.9995,13.6912 18.9551,13.7977 18.8764,13.8764C18.7978,13.955 18.6912,13.9994 18.58,13.9999Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_styler_off.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1908 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M19.56,11.361L13,8.4408V6.9999C13,6.7347 12.8946,6.4804 12.7071,6.2929C12.5196,6.1054 12.2652,5.9999 12,5.9999C11.8022,5.9999 11.6089,5.9413 11.4444,5.8315C11.28,5.7216 11.1518,5.5652 11.0761,5.3825C11.0004,5.1998 10.9806,4.9988 11.0192,4.8049C11.0578,4.6109 11.153,4.4327 11.2929,4.2929C11.4327,4.153 11.6109,4.0578 11.8049,4.0192C11.9989,3.9806 12.2,4.0004 12.3827,4.0761C12.5654,4.1518 12.7216,4.2798 12.8315,4.4443C12.9414,4.6087 13,4.8021 13,4.9999H15C15.0015,4.4496 14.8517,3.9095 14.5668,3.4386C14.2819,2.9678 13.8729,2.5843 13.3847,2.3303C12.8965,2.0762 12.3478,1.9613 11.7987,1.9982C11.2496,2.0351 10.7212,2.2224 10.2714,2.5395C9.8216,2.8566 9.4677,3.2915 9.2484,3.7963C9.0291,4.3011 8.9529,4.8563 9.0282,5.4015C9.1034,5.9467 9.3272,6.4608 9.6749,6.8874C10.0227,7.3139 10.4811,7.6365 11,7.82V8.4499L4.44,11.37C4.0115,11.5562 3.6468,11.8636 3.3909,12.2546C3.1351,12.6455 2.9992,13.1028 3,13.57V13.58C2.9995,13.8979 3.0617,14.2129 3.1831,14.5068C3.3046,14.8006 3.4828,15.0676 3.7076,15.2924C3.9325,15.5172 4.1994,15.6954 4.4933,15.8168C4.7871,15.9382 5.1021,16.0004 5.42,15.9999H7V21.9999H17V15.9999H18.58C18.898,16.0004 19.2129,15.9382 19.5067,15.8168C19.8006,15.6954 20.0676,15.5172 20.2924,15.2924C20.5172,15.0676 20.6954,14.8006 20.8169,14.5068C20.9383,14.2129 21.0005,13.8979 21,13.58V13.57C20.9994,13.1019 20.8631,12.644 20.6075,12.2519C20.3519,11.8598 19.988,11.5504 19.56,11.361ZM18.58,14.0009H17V13.0009H7V14.0009H5.42C5.3642,14.0002 5.3091,13.9887 5.2577,13.9667C5.2064,13.9448 5.1599,13.9129 5.1209,13.873C5.0819,13.833 5.0512,13.7859 5.0304,13.7341C5.0097,13.6822 4.9993,13.6268 5,13.571C4.999,13.4899 5.0222,13.4104 5.0668,13.3427C5.1114,13.275 5.1752,13.222 5.25,13.1908L12,10.1908L18.75,13.1908C18.8245,13.2253 18.8876,13.2804 18.9319,13.3495C18.9761,13.4186 18.9998,13.4989 19,13.581C18.9992,13.692 18.9547,13.7982 18.8761,13.8766C18.7974,13.9551 18.6911,13.9994 18.58,13.9999V14.0009Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_styler_on.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1228 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M15,12V6C15,5.2043 14.6839,4.4413 14.1213,3.8787C13.5587,3.3161 12.7956,3 12,3C11.2044,3 10.4413,3.3161 9.8787,3.8787C9.3161,4.4413 9,5.2043 9,6V12C8.3795,12.4662 7.8759,13.0702 7.5288,13.7644C7.1817,14.4586 7.0007,15.2239 7,16C7.0021,17.0723 7.3531,18.1148 8,18.97V19H8.02C8.4815,19.6206 9.0818,20.1246 9.7729,20.4719C10.4639,20.8192 11.2266,21.0001 12,21.0001C12.7734,21.0001 13.5361,20.8192 14.2271,20.4719C14.9182,20.1246 15.5185,19.6206 15.98,19H16V18.97C16.6469,18.1148 16.9979,17.0723 17,16C16.9993,15.2239 16.8183,14.4586 16.4712,13.7644C16.1241,13.0702 15.6205,12.4662 15,12ZM14.4,17.773L14.367,17.819C14.0952,18.1807 13.744,18.4752 13.3405,18.6799C12.937,18.8846 12.4919,18.9941 12.0395,18.9998C11.5871,19.0055 11.1394,18.9073 10.7309,18.7128C10.3223,18.5184 9.9638,18.2327 9.683,17.878L9.604,17.778C9.2154,17.2664 9.0034,16.6425 9,16C9.0016,15.5346 9.1108,15.0758 9.3189,14.6595C9.5271,14.2432 9.8286,13.8805 10.2,13.6L11,13V6C11,5.7348 11.1054,5.4804 11.2929,5.2929C11.4804,5.1054 11.7348,5 12,5C12.2652,5 12.5196,5.1054 12.7071,5.2929C12.8946,5.4804 13,5.7348 13,6V13L13.8,13.6C14.1714,13.8805 14.4729,14.2432 14.6811,14.6595C14.8892,15.0758 14.9984,15.5346 15,16C14.9967,16.6403 14.7862,17.2623 14.4,17.773V17.773Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_thermostat_off.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (941 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M8,6.5V11.76C8.8027,12.2963 9.4117,13.0766 9.7369,13.9856C10.0622,14.8946 10.0865,15.8841 9.8062,16.8079C9.526,17.7317 8.9561,18.541 8.1807,19.1161C7.4052,19.6912 6.4654,20.0017 5.5,20.0017C4.5346,20.0017 3.5948,19.6912 2.8193,19.1161C2.0439,18.541 1.474,17.7317 1.1938,16.8079C0.9135,15.8841 0.9378,14.8946 1.2631,13.9856C1.5883,13.0766 2.1973,12.2963 3,11.76V6.5C3,5.837 3.2634,5.2011 3.7322,4.7322C4.2011,4.2634 4.837,4 5.5,4C6.163,4 6.7989,4.2634 7.2678,4.7322C7.7366,5.2011 8,5.837 8,6.5ZM3.049,16H7.949C8.0467,15.5132 7.9978,15.0084 7.8084,14.5495C7.619,14.0905 7.2976,13.6981 6.885,13.422L5.998,12.828V6.5C5.998,6.3674 5.9453,6.2402 5.8516,6.1465C5.7578,6.0527 5.6306,6 5.498,6C5.3654,6 5.2382,6.0527 5.1445,6.1465C5.0507,6.2402 4.998,6.3674 4.998,6.5V12.828L4.111,13.422C3.7061,13.6922 3.3887,14.0746 3.1976,14.5223C3.0065,14.97 2.95,15.4637 3.035,15.943C3.0363,15.951 3.0389,15.959 3.0416,15.967C3.0453,15.978 3.049,15.989 3.049,16Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_unknown_off.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (924 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M8,6.5V11.76C8.8027,12.2963 9.4117,13.0766 9.7369,13.9856C10.0622,14.8946 10.0865,15.8841 9.8062,16.8079C9.526,17.7317 8.9561,18.541 8.1807,19.1161C7.4052,19.6912 6.4654,20.0017 5.5,20.0017C4.5346,20.0017 3.5948,19.6912 2.8193,19.1161C2.0439,18.541 1.474,17.7317 1.1938,16.8079C0.9135,15.8841 0.9378,14.8946 1.2631,13.9856C1.5883,13.0766 2.1973,12.2963 3,11.76V6.5C3,5.837 3.2634,5.2011 3.7322,4.7322C4.2011,4.2634 4.837,4 5.5,4C6.163,4 6.7989,4.2634 7.2678,4.7322C7.7366,5.2011 8,5.837 8,6.5ZM3.049,16H7.949C8.0469,15.5134 7.9983,15.0087 7.8093,14.5498C7.6202,14.0909 7.2992,13.6984 6.887,13.422L6,12.828V6.5C6,6.3674 5.9473,6.2402 5.8535,6.1465C5.7598,6.0527 5.6326,6 5.5,6C5.3674,6 5.2402,6.0527 5.1465,6.1465C5.0527,6.2402 5,6.3674 5,6.5V12.828L4.111,13.422C3.7061,13.6922 3.3887,14.0746 3.1976,14.5223C3.0065,14.97 2.95,15.4637 3.035,15.943C3.0363,15.951 3.0389,15.959 3.0416,15.967C3.0453,15.978 3.049,15.989 3.049,16Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_unknown_on.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1581 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M4,16.0001C3.4067,16.0001 2.8266,16.176 2.3333,16.5057C1.8399,16.8353 1.4554,17.3039 1.2284,17.8521C1.0013,18.4002 0.9419,19.0034 1.0576,19.5854C1.1734,20.1673 1.4591,20.7019 1.8787,21.1214C2.2982,21.541 2.8328,21.8267 3.4147,21.9425C3.9967,22.0582 4.5999,21.9988 5.148,21.7717C5.6962,21.5447 6.1648,21.1602 6.4944,20.6668C6.824,20.1735 7,19.5934 7,19.0001C7,18.2045 6.6839,17.4414 6.1213,16.8788C5.5587,16.3162 4.7957,16.0001 4,16.0001ZM4,20.0001C3.8022,20.0001 3.6089,19.9415 3.4444,19.8316C3.28,19.7217 3.1518,19.5655 3.0761,19.3828C3.0004,19.2001 2.9806,18.999 3.0192,18.805C3.0578,18.611 3.153,18.4329 3.2929,18.293C3.4327,18.1532 3.6109,18.0579 3.8049,18.0193C3.9989,17.9807 4.2,18.0005 4.3827,18.0762C4.5654,18.1519 4.7216,18.2801 4.8315,18.4445C4.9413,18.609 5,18.8023 5,19.0001C5,19.2653 4.8946,19.5197 4.7071,19.7072C4.5196,19.8947 4.2652,20.0001 4,20.0001ZM23,20.0001V22.0001H16V20.0001H18.49L12.01,4.5901C11.7747,4.0366 11.3553,3.5814 10.823,3.3016C10.2906,3.0217 9.6779,2.9344 9.0885,3.0544C8.4991,3.1744 7.9693,3.4943 7.5888,3.96C7.2082,4.4257 7.0002,5.0086 7,5.6101V9.0001H9C10.0609,9.0001 11.0783,9.4215 11.8284,10.1717C12.5786,10.9218 13,11.9392 13,13.0001V22.0001H7.99C8.4398,21.4103 8.7508,20.7267 8.9,20.0001H11V13.0001C10.9984,12.4702 10.7872,11.9624 10.4125,11.5876C10.0377,11.2129 9.5299,11.0017 9,11.0001H4V14.0001C3.3113,13.9992 2.6301,14.1422 2,14.4201V9.0001H5V5.6101C5.0002,4.5458 5.3685,3.5144 6.0426,2.6908C6.7165,1.8672 7.6547,1.3021 8.6979,1.0913C9.741,0.8806 10.825,1.0372 11.7659,1.5345C12.7068,2.0319 13.4466,2.8394 13.86,3.8201L20.66,20.0001H23Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_vacuum_off.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (867 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M4,16.0001C3.4067,16.0001 2.8266,16.176 2.3333,16.5057C1.8399,16.8353 1.4554,17.3039 1.2284,17.8521C1.0013,18.4002 0.9419,19.0034 1.0576,19.5854C1.1734,20.1673 1.4591,20.7018 1.8787,21.1214C2.2982,21.541 2.8328,21.8267 3.4147,21.9424C3.9967,22.0582 4.5999,21.9988 5.148,21.7717C5.6962,21.5447 6.1648,21.1602 6.4944,20.6668C6.824,20.1735 7,19.5934 7,19.0001C7,18.2044 6.6839,17.4414 6.1213,16.8788C5.5587,16.3162 4.7957,16.0001 4,16.0001ZM4,20.0001C3.8022,20.0001 3.6089,19.9415 3.4444,19.8316C3.28,19.7217 3.1518,19.5655 3.0761,19.3828C3.0004,19.2001 2.9806,18.999 3.0192,18.805C3.0578,18.611 3.153,18.4329 3.2929,18.293C3.4327,18.1531 3.6109,18.0579 3.8049,18.0193C3.9989,17.9807 4.2,18.0005 4.3827,18.0762C4.5654,18.1519 4.7216,18.2801 4.8315,18.4445C4.9413,18.609 5,18.8023 5,19.0001C5,19.2653 4.8946,19.5196 4.7071,19.7072C4.5196,19.8947 4.2652,20.0001 4,20.0001Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_vacuum_on.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (2132 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M9.64,16.3601C10.2694,16.969 11.1129,17.3061 11.9886,17.2988C12.8643,17.2916 13.7021,16.9405 14.3213,16.3213C14.9406,15.7021 15.2916,14.8642 15.2989,13.9885C15.3061,13.1128 14.9689,12.2693 14.36,11.6399L9.64,16.3601ZM18,2.01L6,2C5.7371,1.9991 5.4766,2.0502 5.2336,2.1504C4.9905,2.2506 4.7696,2.3979 4.5837,2.5838C4.3978,2.7696 4.2505,2.9906 4.1504,3.2336C4.0502,3.4767 3.9991,3.7371 4,4V20C3.9991,20.2629 4.0502,20.5233 4.1504,20.7664C4.2505,21.0094 4.3978,21.2304 4.5837,21.4163C4.7696,21.6022 4.9905,21.7494 5.2336,21.8496C5.4766,21.9498 5.7371,22.0009 6,22H18C18.2629,22.0009 18.5234,21.9498 18.7665,21.8496C19.0095,21.7494 19.2304,21.6022 19.4163,21.4163C19.6022,21.2304 19.7495,21.0094 19.8497,20.7664C19.9498,20.5233 20.0009,20.2629 20,20V4C20.0007,3.7376 19.9493,3.4778 19.8489,3.2354C19.7485,2.993 19.6011,2.773 19.4151,2.5879C19.2291,2.4028 19.0083,2.2564 18.7654,2.1572C18.5225,2.0581 18.2624,2.008 18,2.01ZM11,5C11.1978,5 11.3911,5.0586 11.5556,5.1685C11.72,5.2783 11.8482,5.4347 11.9239,5.6174C11.9996,5.8002 12.0194,6.0011 11.9808,6.1951C11.9422,6.3891 11.847,6.5672 11.7071,6.707C11.5673,6.8469 11.3891,6.9421 11.1951,6.9807C11.0011,7.0193 10.8001,6.9995 10.6173,6.9238C10.4346,6.8481 10.2784,6.7201 10.1685,6.5557C10.0587,6.3912 10,6.1978 10,6C10,5.7348 10.1054,5.4805 10.2929,5.293C10.4804,5.1054 10.7348,5 11,5ZM8,5C8.1978,5 8.3911,5.0586 8.5556,5.1685C8.72,5.2783 8.8482,5.4347 8.9239,5.6174C8.9996,5.8002 9.0194,6.0011 8.9808,6.1951C8.9422,6.3891 8.847,6.5672 8.7071,6.707C8.5673,6.8469 8.3891,6.9421 8.1951,6.9807C8.0011,7.0193 7.8001,6.9995 7.6173,6.9238C7.4346,6.8481 7.2784,6.7201 7.1685,6.5557C7.0587,6.3912 7,6.1978 7,6C7,5.7348 7.1054,5.4805 7.2929,5.293C7.4804,5.1054 7.7348,5 8,5ZM12,19C11.0111,19 10.0444,18.7066 9.2222,18.1572C8.3999,17.6078 7.759,16.827 7.3806,15.9133C7.0022,14.9997 6.9032,13.9946 7.0961,13.0247C7.289,12.0548 7.7652,11.1636 8.4645,10.4644C9.1637,9.7651 10.0547,9.2891 11.0246,9.0962C11.9945,8.9033 12.9998,9.0022 13.9134,9.3806C14.8271,9.7591 15.608,10.3999 16.1574,11.2222C16.7068,12.0444 17,13.0111 17,14C17,15.3261 16.4732,16.598 15.5355,17.5357C14.5979,18.4733 13.3261,19 12,19Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_washer_on.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1783 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M13.553,8.0161C13.1979,7.6625 12.9486,7.2166 12.8333,6.729C12.7179,6.2413 12.741,5.7311 12.9,5.2558C12.9134,5.2214 12.9162,5.1839 12.9082,5.1479C12.9003,5.1119 12.8818,5.0792 12.8552,5.0537C12.8286,5.0281 12.795,5.0109 12.7586,5.0044C12.7223,4.9979 12.6849,5.0023 12.6511,5.0171C8.8941,6.6581 10.4031,10.6938 10.4031,10.7568C10.4028,10.8187 10.3848,10.8792 10.3511,10.9311C10.3174,10.9831 10.2695,11.0243 10.2131,11.0498C10.2031,11.0498 9.974,11.1708 9.769,10.8838C9.5395,10.5707 9.3759,10.2145 9.2879,9.8364C9.1999,9.4583 9.1894,9.0663 9.2571,8.6841C9.2647,8.6434 9.2587,8.6012 9.2398,8.5644C9.2209,8.5276 9.1902,8.4984 9.1527,8.4809C9.1152,8.4635 9.0729,8.459 9.0326,8.4682C8.9923,8.4775 8.9562,8.5001 8.93,8.5322C8.503,9.08 8.2253,9.7288 8.1241,10.416C8.023,11.1032 8.1018,11.805 8.3528,12.4526C8.6039,13.1003 9.0187,13.6719 9.5567,14.1113C10.0946,14.5507 10.7373,14.8431 11.4221,14.9599C15.6071,15.4939 17.1871,11.2899 14.7041,8.9599C14.3381,8.6159 13.909,8.3721 13.553,8.0161ZM13.3241,12.8691C13.0354,13.1235 12.6634,13.2626 12.2787,13.2607C11.8939,13.2589 11.5233,13.116 11.2371,12.8589C11.225,12.8488 11.2159,12.836 11.2107,12.8213C11.2054,12.8065 11.2042,12.7903 11.2072,12.7749C11.2101,12.7595 11.2172,12.7452 11.2275,12.7334C11.2379,12.7216 11.2512,12.7129 11.2661,12.708C11.5164,12.6335 11.7426,12.4939 11.9216,12.3037C12.1005,12.1135 12.226,11.8794 12.2851,11.625C12.3198,11.2109 12.2684,10.7941 12.1341,10.4009C12.067,10.0764 12.087,9.74 12.1921,9.4258C12.196,9.4132 12.2035,9.4023 12.2138,9.394C12.2241,9.3858 12.2366,9.3809 12.2497,9.3799C12.2628,9.3788 12.2759,9.3817 12.2874,9.3882C12.2989,9.3946 12.3081,9.4042 12.3141,9.416C12.6801,10.236 13.8361,10.6222 13.8361,11.6162C13.843,11.8492 13.801,12.081 13.7128,12.2969C13.6246,12.5127 13.4922,12.7076 13.3241,12.8691Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_water_heater_off.xml"
+ line="26"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1632 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M16,2H8C6.9391,2 5.9217,2.4212 5.1716,3.1714C4.4214,3.9215 4,4.9391 4,6V20C4,20.5304 4.2107,21.039 4.5858,21.4141C4.9609,21.7891 5.4696,22 6,22H18C18.5304,22 19.0391,21.7891 19.4142,21.4141C19.7893,21.039 20,20.5304 20,20V6C20,4.9391 19.5786,3.9215 18.8284,3.1714C18.0783,2.4212 17.0609,2 16,2ZM8.93,8.5278C8.9561,8.4957 8.9922,8.4736 9.0325,8.4644C9.0729,8.4551 9.1151,8.4591 9.1526,8.4766C9.1902,8.494 9.2208,8.5237 9.2397,8.5605C9.2586,8.5974 9.2647,8.6395 9.257,8.6802C9.1893,9.0625 9.1998,9.4544 9.2878,9.8325C9.3758,10.2106 9.5395,10.5668 9.769,10.8799C9.969,11.1669 10.203,11.0499 10.213,11.0459C10.2694,11.0204 10.3173,10.9792 10.351,10.9272C10.3847,10.8753 10.4027,10.8148 10.403,10.7529C10.403,10.6899 8.894,6.6532 12.651,5.0132C12.6848,4.9985 12.7223,4.994 12.7586,5.0005C12.7949,5.007 12.8285,5.0238 12.8551,5.0493C12.8817,5.0749 12.9002,5.108 12.9082,5.144C12.9162,5.1801 12.9133,5.2175 12.9,5.2519C12.741,5.7272 12.7178,6.2374 12.8332,6.7251C12.9486,7.2127 13.1979,7.6586 13.553,8.0122C13.909,8.3682 14.338,8.6121 14.704,8.9541C17.187,11.2821 15.604,15.4861 11.422,14.9541C10.7376,14.8371 10.0952,14.5448 9.5576,14.1055C9.0199,13.6662 8.6053,13.0946 8.3543,12.4473C8.1033,11.7999 8.0244,11.0986 8.1252,10.4116C8.2261,9.7247 8.5034,9.0756 8.93,8.5278ZM18,20H6V16C6.7396,15.9897 7.4619,16.2246 8.054,16.668C8.3188,16.8888 8.6527,17.0098 8.9975,17.0098C9.3423,17.0098 9.6762,16.8888 9.941,16.668C10.5357,16.2281 11.2558,15.9907 11.9955,15.9907C12.7352,15.9907 13.4553,16.2281 14.05,16.668C14.3161,16.889 14.6511,17.0103 14.997,17.0103C15.3429,17.0103 15.6779,16.889 15.944,16.668C16.5368,16.2244 17.2597,15.9896 18,16V20Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_water_heater_on.xml"
+ line="26"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (834 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M17.654,7.563L12,2L6.346,7.563C5.6036,8.2877 5.0136,9.1533 4.6108,10.1094C4.2079,11.0654 4.0002,12.0924 4,13.1299C4.0174,15.2343 4.87,17.2458 6.3703,18.7217C7.8705,20.1975 9.8956,21.017 12,21C14.1044,21.017 16.1295,20.1975 17.6297,18.7217C19.13,17.2458 19.9826,15.2343 20,13.1299C20,12.0924 19.7925,11.0654 19.3896,10.1094C18.9867,9.1533 18.3966,8.2875 17.654,7.563ZM12,18C11.7348,18 11.4804,17.8946 11.2929,17.707C11.1054,17.5195 11,17.2652 11,17C11,16.7348 11.1054,16.4805 11.2929,16.293C11.4804,16.1054 11.7348,16 12,16C12.7956,16 13.5587,15.6837 14.1213,15.1211C14.6839,14.5585 15,13.7956 15,13C15,12.7348 15.1054,12.4805 15.2929,12.293C15.4804,12.1054 15.7348,12 16,12C16.2652,12 16.5196,12.1054 16.7071,12.293C16.8946,12.4805 17,12.7348 17,13C16.9984,14.3256 16.4711,15.5964 15.5338,16.5337C14.5964,17.471 13.3256,17.9984 12,18Z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_device_water_on.xml"
+ line="23"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1526 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M480,520Q414,520 367,473Q320,426 320,360Q320,294 367,247Q414,200 480,200Q546,200 593,247Q640,294 640,360Q640,426 593,473Q546,520 480,520ZM160,840L160,728Q160,695 177,666Q194,637 224,622Q275,596 339,578Q403,560 480,560Q557,560 621,578Q685,596 736,622Q766,637 783,666Q800,695 800,728L800,840L160,840ZM240,760L720,760L720,728Q720,717 714.5,708Q709,699 700,694Q664,676 607.5,658Q551,640 480,640Q409,640 352.5,658Q296,676 260,694Q251,699 245.5,708Q240,717 240,728L240,760ZM480,440Q513,440 536.5,416.5Q560,393 560,360Q560,327 536.5,303.5Q513,280 480,280Q447,280 423.5,303.5Q400,327 400,360Q400,393 423.5,416.5Q447,440 480,440ZM39,200L39,120Q56,120 70,113.5Q84,107 95,96Q106,85 112,71Q118,57 118,40L199,40Q199,73 186.5,102Q174,131 152,153Q130,175 101,187.5Q72,200 39,200ZM39,361L39,281Q90,281 133.5,262Q177,243 209,210Q241,177 260,133.5Q279,90 279,40L360,40Q360,106 335,164.5Q310,223 266,267Q222,311 164,336Q106,361 39,361ZM920,361Q854,361 795.5,336Q737,311 693,267Q649,223 624,164.5Q599,106 599,40L679,40Q679,90 698,133.5Q717,177 750,210Q783,243 826.5,262Q870,281 920,281L920,361ZM920,200Q887,200 858,187.5Q829,175 807,153Q785,131 772.5,102Q760,73 760,40L840,40Q840,57 846.5,71Q853,85 864,96Q875,107 889,113.5Q903,120 920,120L920,200ZM480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360Q480,360 480,360ZM480,760L480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760Q480,760 480,760L480,760L480,760Z" />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_head_tracking.xml"
+ line="25"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1366 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M20.000000,5.000000L4.000000,5.000000C2.900000,5.000000 2.000000,5.900000 2.000000,7.000000l0.000000,10.000000c0.000000,1.100000 0.900000,2.000000 2.000000,2.000000l16.000000,0.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000L22.000000,7.000000C22.000000,5.900000 21.100000,5.000000 20.000000,5.000000zM11.000000,8.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000L11.000000,8.000000zM11.000000,11.000000l2.000000,0.000000l0.000000,2.000000l-2.000000,0.000000L11.000000,11.000000zM8.000000,8.000000l2.000000,0.000000l0.000000,2.000000L8.000000,10.000000L8.000000,8.000000zM8.000000,11.000000l2.000000,0.000000l0.000000,2.000000L8.000000,13.000000L8.000000,11.000000zM7.000000,13.000000L5.000000,13.000000l0.000000,-2.000000l2.000000,0.000000L7.000000,13.000000zM7.000000,10.000000L5.000000,10.000000L5.000000,8.000000l2.000000,0.000000L7.000000,10.000000zM16.000000,17.000000L8.000000,17.000000l0.000000,-2.000000l8.000000,0.000000L16.000000,17.000000zM16.000000,13.000000l-2.000000,0.000000l0.000000,-2.000000l2.000000,0.000000L16.000000,13.000000zM16.000000,10.000000l-2.000000,0.000000L14.000000,8.000000l2.000000,0.000000L16.000000,10.000000zM19.000000,13.000000l-2.000000,0.000000l0.000000,-2.000000l2.000000,0.000000L19.000000,13.000000zM19.000000,10.000000l-2.000000,0.000000L17.000000,8.000000l2.000000,0.000000L19.000000,10.000000z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable-sw900dp/ic_ime_switcher_default.xml"
+ line="23"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1395 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M10,12Q8.35,12 7.175,10.825Q6,9.65 6,8Q6,6.35 7.175,5.175Q8.35,4 10,4Q11.65,4 12.825,5.175Q14,6.35 14,8Q14,9.65 12.825,10.825Q11.65,12 10,12ZM2,20V17.2Q2,16.375 2.425,15.65Q2.85,14.925 3.6,14.55Q4.875,13.9 6.475,13.45Q8.075,13 10,13Q10.2,13 10.35,13Q10.5,13 10.65,13.05Q10.45,13.5 10.312,13.988Q10.175,14.475 10.1,15H10Q8.225,15 6.812,15.45Q5.4,15.9 4.5,16.35Q4.275,16.475 4.138,16.7Q4,16.925 4,17.2V18H10.3Q10.45,18.525 10.7,19.038Q10.95,19.55 11.25,20ZM16,21L15.7,19.5Q15.4,19.375 15.137,19.238Q14.875,19.1 14.6,18.9L13.15,19.35L12.15,17.65L13.3,16.65Q13.25,16.3 13.25,16Q13.25,15.7 13.3,15.35L12.15,14.35L13.15,12.65L14.6,13.1Q14.875,12.9 15.137,12.762Q15.4,12.625 15.7,12.5L16,11H18L18.3,12.5Q18.6,12.625 18.863,12.775Q19.125,12.925 19.4,13.15L20.85,12.65L21.85,14.4L20.7,15.4Q20.75,15.7 20.75,16.025Q20.75,16.35 20.7,16.65L21.85,17.65L20.85,19.35L19.4,18.9Q19.125,19.1 18.863,19.238Q18.6,19.375 18.3,19.5L18,21ZM17,18Q17.825,18 18.413,17.413Q19,16.825 19,16Q19,15.175 18.413,14.587Q17.825,14 17,14Q16.175,14 15.588,14.587Q15,15.175 15,16Q15,16.825 15.588,17.413Q16.175,18 17,18ZM10,10Q10.825,10 11.413,9.412Q12,8.825 12,8Q12,7.175 11.413,6.588Q10.825,6 10,6Q9.175,6 8.588,6.588Q8,7.175 8,8Q8,8.825 8.588,9.412Q9.175,10 10,10ZM10,8Q10,8 10,8Q10,8 10,8Q10,8 10,8Q10,8 10,8Q10,8 10,8Q10,8 10,8Q10,8 10,8Q10,8 10,8ZM10,15Q10,15 10,15Q10,15 10,15Q10,15 10,15Q10,15 10,15Q10,15 10,15Q10,15 10,15Z"/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_manage_users.xml"
+ line="22"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (866 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M14.95,11.3l1.62,-1.61C16.84,10.41 17,11.18 17,12s-0.16,1.61 -0.44,2.33l-1.61,-1.61C14.56,12.33 14.56,11.69 14.95,11.3zM18.69,7.54c-0.26,0.26 -0.32,0.65 -0.17,0.98c0.47,1.07 0.72,2.24 0.72,3.47c0,1.24 -0.26,2.43 -0.73,3.49c-0.14,0.32 -0.09,0.69 0.16,0.94c0.4,0.4 1.09,0.29 1.34,-0.23c0.63,-1.3 0.98,-2.76 0.98,-4.3c-0.01,-1.46 -0.33,-2.86 -0.91,-4.12C19.84,7.23 19.12,7.11 18.69,7.54zM15.26,15.74c0.41,0.41 0.41,1.07 0,1.48l-4.51,4.51C10.57,21.89 10.32,22 10.04,22C9.47,22 9,21.53 9,20.96v-6.45l-4.05,4.05c-0.41,0.41 -1.06,0.41 -1.47,0s-0.41,-1.06 0,-1.47L8.57,12L3.48,6.9c-0.41,-0.41 -0.41,-1.06 0,-1.47s1.06,-0.41 1.47,0L9,9.49V3.04C9,2.47 9.47,2 10.04,2c0.28,0 0.53,0.11 0.72,0.29l4.5,4.5c0.41,0.41 0.41,1.07 0,1.48L11.51,12L15.26,15.74zM13.14,7.53l-2.15,-2.15v4.3C10.99,9.68 13.14,7.53 13.14,7.53zM13.14,16.47l-2.15,-2.15v4.3C10.99,18.62 13.14,16.47 13.14,16.47z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml"
+ line="23"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (836 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M2,12C2,6.48 6.47,2 11.99,2C17.52,2 22,6.48 22,12c0,0.34 -0.02,0.67 -0.05,1h-2.02c0.04,-0.33 0.07,-0.66 0.07,-1c0,-0.69 -0.1,-1.36 -0.26,-2h-3.38c0.08,0.66 0.14,1.32 0.14,2c0,0.34 -0.01,0.67 -0.04,1h-2.01c0.03,-0.33 0.05,-0.66 0.05,-1c0,-0.68 -0.07,-1.35 -0.16,-2H9.66c-0.09,0.65 -0.16,1.32 -0.16,2s0.07,1.34 0.16,2H13v2h-2.91c0.43,1.43 1.08,2.76 1.91,3.96V20h1v1.95C12.67,21.98 12.33,22 11.99,22C6.47,22 2,17.52 2,12zM15.97,8h2.95c-0.96,-1.65 -2.49,-2.93 -4.33,-3.56C15.19,5.55 15.65,6.75 15.97,8zM13.91,8C13.48,6.57 12.83,5.24 12,4.04c-0.83,1.2 -1.48,2.53 -1.91,3.96H13.91zM4,12c0,0.69 0.1,1.36 0.26,2h3.38c-0.08,-0.66 -0.14,-1.32 -0.14,-2s0.06,-1.34 0.14,-2H4.26C4.1,10.64 4,11.31 4,12zM8.03,16H5.08c0.96,1.66 2.49,2.93 4.33,3.56C8.81,18.45 8.35,17.25 8.03,16zM5.08,8h2.95c0.32,-1.25 0.78,-2.45 1.38,-3.56C7.57,5.07 6.04,6.34 5.08,8z""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_qs_no_internet_unavailable.xml"
+ line="23"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1847 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M13.85,22.25h-3.7c-0.74,0 -1.36,-0.54 -1.45,-1.27l-0.27,-1.89c-0.27,-0.14 -0.53,-0.29 -0.79,-0.46l-1.8,0.72c-0.7,0.26 -1.47,-0.03 -1.81,-0.65L2.2,15.53c-0.35,-0.66 -0.2,-1.44 0.36,-1.88l1.53,-1.19c-0.01,-0.15 -0.02,-0.3 -0.02,-0.46c0,-0.15 0.01,-0.31 0.02,-0.46l-1.52,-1.19C1.98,9.9 1.83,9.09 2.2,8.47l1.85,-3.19c0.34,-0.62 1.11,-0.9 1.79,-0.63l1.81,0.73c0.26,-0.17 0.52,-0.32 0.78,-0.46l0.27,-1.91c0.09,-0.7 0.71,-1.25 1.44,-1.25h3.7c0.74,0 1.36,0.54 1.45,1.27l0.27,1.89c0.27,0.14 0.53,0.29 0.79,0.46l1.8,-0.72c0.71,-0.26 1.48,0.03 1.82,0.65l1.84,3.18c0.36,0.66 0.2,1.44 -0.36,1.88l-1.52,1.19c0.01,0.15 0.02,0.3 0.02,0.46s-0.01,0.31 -0.02,0.46l1.52,1.19c0.56,0.45 0.72,1.23 0.37,1.86l-1.86,3.22c-0.34,0.62 -1.11,0.9 -1.8,0.63l-1.8,-0.72c-0.26,0.17 -0.52,0.32 -0.78,0.46l-0.27,1.91C15.21,21.71 14.59,22.25 13.85,22.25zM13.32,20.72c0,0.01 0,0.01 0,0.02L13.32,20.72zM10.68,20.7l0,0.02C10.69,20.72 10.69,20.71 10.68,20.7zM10.62,20.25h2.76l0.37,-2.55l0.53,-0.22c0.44,-0.18 0.88,-0.44 1.34,-0.78l0.45,-0.34l2.38,0.96l1.38,-2.4l-2.03,-1.58l0.07,-0.56c0.03,-0.26 0.06,-0.51 0.06,-0.78c0,-0.27 -0.03,-0.53 -0.06,-0.78l-0.07,-0.56l2.03,-1.58l-1.39,-2.4l-2.39,0.96l-0.45,-0.35c-0.42,-0.32 -0.87,-0.58 -1.33,-0.77L13.75,6.3l-0.37,-2.55h-2.76L10.25,6.3L9.72,6.51C9.28,6.7 8.84,6.95 8.38,7.3L7.93,7.63L5.55,6.68L4.16,9.07l2.03,1.58l-0.07,0.56C6.09,11.47 6.06,11.74 6.06,12c0,0.26 0.02,0.53 0.06,0.78l0.07,0.56l-2.03,1.58l1.38,2.4l2.39,-0.96l0.45,0.35c0.43,0.33 0.86,0.58 1.33,0.77l0.53,0.22L10.62,20.25zM18.22,17.72c0,0.01 -0.01,0.02 -0.01,0.03L18.22,17.72zM5.77,17.71l0.01,0.02C5.78,17.72 5.77,17.71 5.77,17.71zM3.93,9.47L3.93,9.47C3.93,9.47 3.93,9.47 3.93,9.47zM18.22,6.27c0,0.01 0.01,0.02 0.01,0.02L18.22,6.27zM5.79,6.25L5.78,6.27C5.78,6.27 5.79,6.26 5.79,6.25zM13.31,3.28c0,0.01 0,0.01 0,0.02L13.31,3.28zM10.69,3.26l0,0.02C10.69,3.27 10.69,3.27 10.69,3.26z"/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_settings.xml"
+ line="22"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1847 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M13.85,22.25h-3.7c-0.74,0 -1.36,-0.54 -1.45,-1.27l-0.27,-1.89c-0.27,-0.14 -0.53,-0.29 -0.79,-0.46l-1.8,0.72c-0.7,0.26 -1.47,-0.03 -1.81,-0.65L2.2,15.53c-0.35,-0.66 -0.2,-1.44 0.36,-1.88l1.53,-1.19c-0.01,-0.15 -0.02,-0.3 -0.02,-0.46c0,-0.15 0.01,-0.31 0.02,-0.46l-1.52,-1.19C1.98,9.9 1.83,9.09 2.2,8.47l1.85,-3.19c0.34,-0.62 1.11,-0.9 1.79,-0.63l1.81,0.73c0.26,-0.17 0.52,-0.32 0.78,-0.46l0.27,-1.91c0.09,-0.7 0.71,-1.25 1.44,-1.25h3.7c0.74,0 1.36,0.54 1.45,1.27l0.27,1.89c0.27,0.14 0.53,0.29 0.79,0.46l1.8,-0.72c0.71,-0.26 1.48,0.03 1.82,0.65l1.84,3.18c0.36,0.66 0.2,1.44 -0.36,1.88l-1.52,1.19c0.01,0.15 0.02,0.3 0.02,0.46s-0.01,0.31 -0.02,0.46l1.52,1.19c0.56,0.45 0.72,1.23 0.37,1.86l-1.86,3.22c-0.34,0.62 -1.11,0.9 -1.8,0.63l-1.8,-0.72c-0.26,0.17 -0.52,0.32 -0.78,0.46l-0.27,1.91C15.21,21.71 14.59,22.25 13.85,22.25zM13.32,20.72c0,0.01 0,0.01 0,0.02L13.32,20.72zM10.68,20.7l0,0.02C10.69,20.72 10.69,20.71 10.68,20.7zM10.62,20.25h2.76l0.37,-2.55l0.53,-0.22c0.44,-0.18 0.88,-0.44 1.34,-0.78l0.45,-0.34l2.38,0.96l1.38,-2.4l-2.03,-1.58l0.07,-0.56c0.03,-0.26 0.06,-0.51 0.06,-0.78c0,-0.27 -0.03,-0.53 -0.06,-0.78l-0.07,-0.56l2.03,-1.58l-1.39,-2.4l-2.39,0.96l-0.45,-0.35c-0.42,-0.32 -0.87,-0.58 -1.33,-0.77L13.75,6.3l-0.37,-2.55h-2.76L10.25,6.3L9.72,6.51C9.28,6.7 8.84,6.95 8.38,7.3L7.93,7.63L5.55,6.68L4.16,9.07l2.03,1.58l-0.07,0.56C6.09,11.47 6.06,11.74 6.06,12c0,0.26 0.02,0.53 0.06,0.78l0.07,0.56l-2.03,1.58l1.38,2.4l2.39,-0.96l0.45,0.35c0.43,0.33 0.86,0.58 1.33,0.77l0.53,0.22L10.62,20.25zM18.22,17.72c0,0.01 -0.01,0.02 -0.01,0.03L18.22,17.72zM5.77,17.71l0.01,0.02C5.78,17.72 5.77,17.71 5.77,17.71zM3.93,9.47L3.93,9.47C3.93,9.47 3.93,9.47 3.93,9.47zM18.22,6.27c0,0.01 0.01,0.02 0.01,0.02L18.22,6.27zM5.79,6.25L5.78,6.27C5.78,6.27 5.79,6.26 5.79,6.25zM13.31,3.28c0,0.01 0,0.01 0,0.02L13.31,3.28zM10.69,3.26l0,0.02C10.69,3.27 10.69,3.27 10.69,3.26z"/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_settings_24dp.xml"
+ line="25"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1227 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M920,401Q848,401 782,373.5Q716,346 665,295Q614,244 586.5,178Q559,112 559,40L639,40Q639,97 660,148Q681,199 721,239Q761,279 812,300.5Q863,322 920,322L920,401ZM920,242Q879,242 842.5,227Q806,212 777,183Q748,154 733,117.5Q718,81 718,40L797,40Q797,65 806.5,87.5Q816,110 833,127Q850,144 872.5,153Q895,162 920,162L920,242ZM400,520Q334,520 287,473Q240,426 240,360Q240,294 287,247Q334,200 400,200Q466,200 513,247Q560,294 560,360Q560,426 513,473Q466,520 400,520ZM80,840L80,728Q80,695 97,666Q114,637 144,622Q195,596 259,578Q323,560 400,560Q477,560 541,578Q605,596 656,622Q686,637 703,666Q720,695 720,728L720,840L80,840ZM160,760L640,760L640,728Q640,717 634.5,708Q629,699 620,694Q584,676 527.5,658Q471,640 400,640Q329,640 272.5,658Q216,676 180,694Q171,699 165.5,708Q160,717 160,728L160,760ZM400,440Q433,440 456.5,416.5Q480,393 480,360Q480,327 456.5,303.5Q433,280 400,280Q367,280 343.5,303.5Q320,327 320,360Q320,393 343.5,416.5Q367,440 400,440ZM400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360ZM400,760L400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760L400,760L400,760Z" />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_spatial_audio.xml"
+ line="25"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (1224 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M750,550L806,494Q766,454 743.5,402.5Q721,351 721,294Q721,237 743.5,186Q766,135 806,95L750,37Q699,88 670,155Q641,222 641,294Q641,366 670,432.5Q699,499 750,550ZM862,436L918,380Q901,363 891,341Q881,319 881,294Q881,269 891,247Q901,225 918,208L862,151Q833,180 817,216Q801,252 801,293Q801,334 817,371Q833,408 862,436ZM400,520Q334,520 287,473Q240,426 240,360Q240,294 287,247Q334,200 400,200Q466,200 513,247Q560,294 560,360Q560,426 513,473Q466,520 400,520ZM80,840L80,728Q80,695 97,666Q114,637 144,622Q195,596 259,578Q323,560 400,560Q477,560 541,578Q605,596 656,622Q686,637 703,666Q720,695 720,728L720,840L80,840ZM160,760L640,760L640,728Q640,717 634.5,708Q629,699 620,694Q584,676 527.5,658Q471,640 400,640Q329,640 272.5,658Q216,676 180,694Q171,699 165.5,708Q160,717 160,728L160,760ZM400,440Q433,440 456.5,416.5Q480,393 480,360Q480,327 456.5,303.5Q433,280 400,280Q367,280 343.5,303.5Q320,327 320,360Q320,393 343.5,416.5Q367,440 400,440ZM400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360Q400,360 400,360ZM400,760L400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760Q400,760 400,760L400,760L400,760Z" />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/ic_spatial_audio_off.xml"
+ line="25"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (921 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData="M11.95,18Q12.475,18 12.838,17.637Q13.2,17.275 13.2,16.75Q13.2,16.225 12.838,15.863Q12.475,15.5 11.95,15.5Q11.425,15.5 11.062,15.863Q10.7,16.225 10.7,16.75Q10.7,17.275 11.062,17.637Q11.425,18 11.95,18ZM11.05,14.15H12.9Q12.9,13.325 13.088,12.85Q13.275,12.375 14.15,11.55Q14.8,10.9 15.175,10.312Q15.55,9.725 15.55,8.9Q15.55,7.5 14.525,6.75Q13.5,6 12.1,6Q10.675,6 9.788,6.75Q8.9,7.5 8.55,8.55L10.2,9.2Q10.325,8.75 10.763,8.225Q11.2,7.7 12.1,7.7Q12.9,7.7 13.3,8.137Q13.7,8.575 13.7,9.1Q13.7,9.6 13.4,10.037Q13.1,10.475 12.65,10.85Q11.55,11.825 11.3,12.325Q11.05,12.825 11.05,14.15ZM12,22Q9.925,22 8.1,21.212Q6.275,20.425 4.925,19.075Q3.575,17.725 2.788,15.9Q2,14.075 2,12Q2,9.925 2.788,8.1Q3.575,6.275 4.925,4.925Q6.275,3.575 8.1,2.787Q9.925,2 12,2Q14.075,2 15.9,2.787Q17.725,3.575 19.075,4.925Q20.425,6.275 21.212,8.1Q22,9.925 22,12Q22,14.075 21.212,15.9Q20.425,17.725 19.075,19.075Q17.725,20.425 15.9,21.212Q14.075,22 12,22Z"/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/media_output_status_help.xml"
+ line="25"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="ViewHolder"
+ message="Unconditional layout inflation from view adapter: Should use View Holder pattern (use recycled view passed into this method as the second parameter) for smoother scrolling"
+ errorLine1=" layoutInflater.inflate("
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt"
+ line="229"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="HandlerLeak"
+ message="This `Handler` class should be static or leaks might occur (anonymous android.os.Handler)"
+ errorLine1=" private Handler mHandler = new Handler() {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/GestureRecorder.java"
+ line="144"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="HandlerLeak"
+ message="This `Handler` class should be static or leaks might occur (anonymous android.os.Handler)"
+ errorLine1=" private Handler mHandler = new Handler() {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java"
+ line="2165"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="HandlerLeak"
+ message="This `Handler` class should be static or leaks might occur (com.android.systemui.keyboard.KeyboardUI.KeyboardUIHandler)"
+ errorLine1=" private final class KeyboardUIHandler extends Handler {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java"
+ line="430"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="HandlerLeak"
+ message="This `Handler` class should be static or leaks might occur (anonymous android.os.Handler)"
+ errorLine1=" private Handler mHandler = new Handler() {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/logcat/LogAccessDialogActivity.java"
+ line="171"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="HandlerLeak"
+ message="This `Handler` class should be static or leaks might occur (com.android.systemui.shortcut.ShortcutKeyServiceProxy.H)"
+ errorLine1=" private final class H extends Handler {"
+ errorLine2=" ~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyServiceProxy.java"
+ line="49"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="MergeRootFrame"
+ message="This `<FrameLayout>` can be replaced with a `<merge>` tag"
+ errorLine1="<FrameLayout"
+ errorLine2="^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/controls_detail_dialog.xml"
+ line="18"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="MergeRootFrame"
+ message="This `<FrameLayout>` can be replaced with a `<merge>` tag"
+ errorLine1="<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android""
+ errorLine2="^">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/rotate_suggestion.xml"
+ line="17"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="UseValueOf"
+ message="Use `Long.valueOf(c2.getLastInteractionTimestamp())` instead"
+ errorLine1=" .sorted((c1, c2) -> new Long(c2.getLastInteractionTimestamp()).compareTo("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java"
+ line="307"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="UseValueOf"
+ message="Use `Long.valueOf(c1.getLastInteractionTimestamp())` instead"
+ errorLine1=" new Long(c1.getLastInteractionTimestamp())))"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java"
+ line="308"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="DisableBaselineAlignment"
+ message="Set `android:baselineAligned="false"` on this element for better performance"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/controls_app_item.xml"
+ line="22"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="DisableBaselineAlignment"
+ message="Set `android:baselineAligned="false"` on this element for better performance"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+ line="93"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="DisableBaselineAlignment"
+ message="Set `android:baselineAligned="false"` on this element for better performance"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+ line="199"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="DisableBaselineAlignment"
+ message="Set `android:baselineAligned="false"` on this element for better performance"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+ line="250"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="DisableBaselineAlignment"
+ message="Set `android:baselineAligned="false"` on this element for better performance"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_list_item.xml"
+ line="25"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="DisableBaselineAlignment"
+ message="Set `android:baselineAligned="false"` on this element for better performance"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_v2.xml"
+ line="63"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="DisableBaselineAlignment"
+ message="Set `android:baselineAligned="false"` on this element for better performance"
+ errorLine1="<LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/qs_dialog_secondary_mobile_network.xml"
+ line="17"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="InefficientWeight"
+ message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+ errorLine1=" android:layout_width="wrap_content""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+ line="114"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="InefficientWeight"
+ message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+ errorLine1=" android:layout_width="wrap_content""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+ line="150"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="InefficientWeight"
+ message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+ errorLine1=" android:layout_width="wrap_content""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+ line="208"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="InefficientWeight"
+ message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+ errorLine1=" android:layout_width="wrap_content""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+ line="275"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="InefficientWeight"
+ message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+ errorLine1=" android:layout_width="wrap_content""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_list_item.xml"
+ line="48"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="InefficientWeight"
+ message="Use a `layout_height` of `0dp` instead of `wrap_content` for better performance"
+ errorLine1=" android:layout_height="wrap_content""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_output_dialog.xml"
+ line="109"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="InefficientWeight"
+ message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+ errorLine1=" android:layout_width="wrap_content""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_with_content.xml"
+ line="38"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="InefficientWeight"
+ message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+ errorLine1=" android:layout_width="wrap_content""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_with_content.xml"
+ line="129"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="InefficientWeight"
+ message="Use a `layout_height` of `0dp` instead of `wrap_content` for better performance"
+ errorLine1=" android:layout_height="wrap_content""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_small.xml"
+ line="38"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="InefficientWeight"
+ message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+ errorLine1=" android:layout_width="wrap_content""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_v2.xml"
+ line="73"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="InefficientWeight"
+ message="Use a `layout_width` of `0dp` instead of `match_parent` for better performance"
+ errorLine1=" android:layout_width="match_parent""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/qs_dialog_secondary_mobile_network.xml"
+ line="38"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="InefficientWeight"
+ message="Use a `layout_height` of `0dp` instead of `wrap_content` for better performance"
+ errorLine1=" android:layout_height="wrap_content""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/remote_input.xml"
+ line="79"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="InefficientWeight"
+ message="Use a `layout_width` of `0dp` instead of `wrap_content` for better performance"
+ errorLine1=" android:layout_width="wrap_content""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/status_bar_notification_section_header.xml"
+ line="37"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="NestedWeights"
+ message="Nested weights are bad for performance"
+ errorLine1=" android:layout_weight="1""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_space_placeholder_layout.xml"
+ line="47"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `?android:colorBackground` with a theme that also paints a background (inferred theme is `@android_style/Theme_Translucent_NoTitleBar_Fullscreen`)"
+ errorLine1=" android:background="?android:colorBackground""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/auth_biometric_background.xml"
+ line="20"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `?android:attr/colorBackground` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+ errorLine1=" android:background="?android:attr/colorBackground">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+ line="29"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `?android:attr/dividerHorizontal` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+ errorLine1=" android:background="?android:attr/dividerHorizontal" />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/keyboard_shortcuts_category_separator.xml"
+ line="25"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `?android:attr/colorBackground` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+ errorLine1=" android:background="?android:attr/colorBackground""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_projection_recent_tasks.xml"
+ line="22"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `@drawable/system_bar_background` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+ errorLine1=" android:background="@drawable/system_bar_background">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/navigation_bar.xml"
+ line="27"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `?androidprv:attr/materialColorOnSurfaceVariant` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+ errorLine1=" android:background="?androidprv:attr/materialColorOnSurfaceVariant" />"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_children_divider.xml"
+ line="24"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `?androidprv:attr/materialColorSurfaceContainerHigh` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+ errorLine1=" android:background="?androidprv:attr/materialColorSurfaceContainerHigh""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_snooze.xml"
+ line="26"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `?android:attr/colorAccent` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+ errorLine1=" android:background="?android:attr/colorAccent">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+ line="31"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `?android:attr/colorAccent` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+ errorLine1=" android:background="?android:attr/colorAccent""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+ line="28"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `?android:attr/colorAccent` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+ errorLine1=" android:background="?android:attr/colorAccent""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+ line="28"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `@drawable/status_bar_user_chip_bg` with a theme that also paints a background (inferred theme is `@style/Theme.SystemUI`)"
+ errorLine1=" android:background="@drawable/status_bar_user_chip_bg""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/status_bar_user_chip_container.xml"
+ line="26"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="UselessLeaf"
+ message="This `LinearLayout` view is unnecessary (no children, no `background`, no `id`, no `style`)"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout-land/global_actions_grid.xml"
+ line="37"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="UselessLeaf"
+ message="This `LinearLayout` view is unnecessary (no children, no `background`, no `id`, no `style`)"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout-land/global_actions_grid.xml"
+ line="43"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="UselessLeaf"
+ message="This `LinearLayout` view is unnecessary (no children, no `background`, no `id`, no `style`)"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout-land/global_actions_grid.xml"
+ line="49"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="UselessLeaf"
+ message="This `LinearLayout` view is unnecessary (no children, no `background`, no `id`, no `style`)"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/global_actions_grid.xml"
+ line="73"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="UselessLeaf"
+ message="This `LinearLayout` view is unnecessary (no children, no `background`, no `id`, no `style`)"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/global_actions_grid.xml"
+ line="79"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="UselessLeaf"
+ message="This `LinearLayout` view is unnecessary (no children, no `background`, no `id`, no `style`)"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/global_actions_grid.xml"
+ line="85"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `ScrollView` layout or its `FrameLayout` parent is possibly unnecessary"
+ errorLine1=" <ScrollView"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/alert_dialog_systemui.xml"
+ line="39"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `LinearLayout` layout or its `FrameLayout` parent is possibly unnecessary"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/combined_qs_header.xml"
+ line="128"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `LinearLayout` layout or its `FrameLayout` parent is possibly unnecessary"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/controls_detail_dialog.xml"
+ line="23"
+ column="4"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `LinearLayout` layout or its `LinearLayout` parent is unnecessary"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+ line="58"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `RelativeLayout` layout or its `LinearLayout` parent is possibly unnecessary"
+ errorLine1=" <RelativeLayout"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/global_actions_view.xml"
+ line="37"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `RelativeLayout` layout or its `FrameLayout` parent is unnecessary"
+ errorLine1=" <RelativeLayout"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/magnifier_controllers.xml"
+ line="25"
+ column="4"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `FrameLayout` layout or its `LinearLayout` parent is unnecessary"
+ errorLine1=" <FrameLayout"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_output_list_item.xml"
+ line="24"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `LinearLayout` layout or its `FrameLayout` parent is possibly unnecessary; transfer the `background` attribute to the other view"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notif_half_shelf.xml"
+ line="28"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `LinearLayout` layout or its `LinearLayout` parent is possibly unnecessary; transfer the `background` attribute to the other view"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_space_activity_no_conversations.xml"
+ line="69"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `LinearLayout` layout or its `LinearLayout` parent is possibly unnecessary; transfer the `background` attribute to the other view"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_space_initial_layout.xml"
+ line="23"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `LinearLayout` layout or its `LinearLayout` parent is possibly unnecessary; transfer the `background` attribute to the other view"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_space_placeholder_layout.xml"
+ line="23"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `LinearLayout` layout or its `LinearLayout` parent is unnecessary; transfer the `background` attribute to the other view"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_space_tile_view.xml"
+ line="24"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `LinearLayout` layout or its `LinearLayout` parent is unnecessary; transfer the `background` attribute to the other view"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_space_tile_view.xml"
+ line="32"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `LinearLayout` layout or its `FrameLayout` parent is possibly unnecessary; transfer the `background` attribute to the other view"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_empty.xml"
+ line="22"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `RelativeLayout` layout or its `LinearLayout` parent is unnecessary; transfer the `background` attribute to the other view"
+ errorLine1=" <RelativeLayout"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_with_content.xml"
+ line="28"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `LinearLayout` layout or its `FrameLayout` parent is possibly unnecessary; transfer the `background` attribute to the other view"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_small.xml"
+ line="22"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `LinearLayout` layout or its `FrameLayout` parent is possibly unnecessary; transfer the `background` attribute to the other view"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_small_horizontal.xml"
+ line="22"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `ScrollView` layout or its `LinearLayout` parent is unnecessary"
+ errorLine1=" <ScrollView"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_record_dialog.xml"
+ line="24"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `FrameLayout` layout or its `FrameLayout` parent is possibly unnecessary"
+ errorLine1=" <FrameLayout"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/status_bar.xml"
+ line="66"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `LinearLayout` layout or its `LinearLayout` parent is unnecessary"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/user_switcher_fullscreen_popup_item.xml"
+ line="24"
+ column="4"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `LinearLayout` layout or its `FrameLayout` parent is unnecessary; transfer the `background` attribute to the other view"
+ errorLine1=" <LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/volume_dialog_row.xml"
+ line="29"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="RedundantNamespace"
+ message="This namespace declaration is redundant"
+ errorLine1=" <shape xmlns:android="http://schemas.android.com/apk/res/android">"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable/rounded_ripple.xml"
+ line="19"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="UnusedNamespace"
+ message="Unused namespace `systemui`"
+ errorLine1=" xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/status_bar.xml"
+ line="23"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Stoor tans skermkiekie..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-af/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"ቅጽበታዊ ገፅ ዕይታ በማስቀመጥ ላይ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"جارٍ حفظ لقطة الشاشة..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ar/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Skrinşot yadda saxlanır..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-az/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Čuvanje snimka ekrana..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Захаванне скрыншота..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-be/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Екранната снимка се запазва..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"স্ক্রিনশট সেভ করা হচ্ছে..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bn/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Spašavanje snimka ekrana..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bs/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"S\'està desant la captura de pantalla..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ca/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Ukládání snímku obrazovky..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-cs/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Gemmer screenshot..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-da/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Screenshot wird gespeichert..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-de/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Αποθήκευση στιγμιότυπου οθόνης..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-el/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Guardando la captura de pantalla..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es-rUS/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Guardando captura..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Kuvatõmmise salvestamine ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-et/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Tallennetaan kuvakaappausta..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fi/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"स्क्रीनशॉट सहेजा जा रहा है..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hi/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Spremanje snimke zaslona..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Képernyőkép mentése..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hu/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Սքրինշոթը պահվում է..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hy/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Menyimpan screenshot..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-in/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"המערכת שומרת את צילום המסך..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-iw/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"スクリーンショットを保存しています..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ja/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"កំពុងរក្សាទុករូបថតអេក្រង់..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-km/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"캡쳐화면 저장 중..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Скриншот сакталууда..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ky/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"ກຳລັງບັນທຶກພາບໜ້າຈໍ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lo/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Išsaugoma ekrano kopija..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Notiek ekrānuzņēmuma saglabāšana..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lv/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Сликата на екранот се зачувува..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mk/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നു..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ml/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Menyimpan tangkapan skrin..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ms/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Screenshot opslaan..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-nl/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Zapisywanie zrzutu ekranu..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pl/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Salvando captura de tela..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"A guardar captura de ecrã..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Salvando captura de tela..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Se salvează captura de ecran..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Сохранение..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ru/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Prebieha ukladanie snímky obrazovky..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sk/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Shranjevanje posnetka zaslona ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Чување снимка екрана..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Skärmbilden sparas ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sv/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Inahifadhi picha ya skrini..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"กำลังบันทึกภาพหน้าจอ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Ekran görüntüsü kaydediliyor..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tr/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Збереження знімка екрана..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-uk/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Đang lưu ảnh chụp màn hình..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-vi/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"正在保存屏幕截图..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rCN/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"正在儲存螢幕擷取畫面..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rHK/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="screenshot_saving_title" msgid="2298349784913287333">"Ilondoloz umfanekiso weskrini..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu/strings.xml"
+ line="77"
+ column="72"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"በማብራት ላይ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am/strings.xml"
+ line="292"
+ column="99"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Aktiv edilir..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-az/strings.xml"
+ line="292"
+ column="99"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Uključuje se..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings.xml"
+ line="292"
+ column="99"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Включва се..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg/strings.xml"
+ line="292"
+ column="99"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"កំពុងបើក..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-km/strings.xml"
+ line="292"
+ column="99"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ಆನ್ ಮಾಡಲಾಗುತ್ತಿದೆ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kn/strings.xml"
+ line="292"
+ column="99"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"켜는 중..."</string>"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko/strings.xml"
+ line="292"
+ column="99"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"ກຳລັງເປີດ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lo/strings.xml"
+ line="292"
+ column="99"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"A ativar..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings.xml"
+ line="292"
+ column="99"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Se activează..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro/strings.xml"
+ line="292"
+ column="99"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Укључује се..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr/strings.xml"
+ line="292"
+ column="99"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Inawasha..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw/strings.xml"
+ line="292"
+ column="99"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"กำลังเปิด..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th/strings.xml"
+ line="292"
+ column="99"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_bluetooth_secondary_label_transient" msgid="3882884317600669650">"Iyavula..."</string>"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu/strings.xml"
+ line="292"
+ column="99"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"በማብራት ላይ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am/strings.xml"
+ line="308"
+ column="94"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Aktiv edilir..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-az/strings.xml"
+ line="308"
+ column="94"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Uključuje se..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings.xml"
+ line="308"
+ column="94"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Включва се..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg/strings.xml"
+ line="308"
+ column="94"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"កំពុងបើក..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-km/strings.xml"
+ line="308"
+ column="94"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"ಆನ್ ಮಾಡಲಾಗುತ್ತಿದೆ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kn/strings.xml"
+ line="308"
+ column="94"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"켜는 중..."</string>"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko/strings.xml"
+ line="308"
+ column="94"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"ກຳລັງເປີດ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lo/strings.xml"
+ line="308"
+ column="94"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"A ativar..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings.xml"
+ line="308"
+ column="94"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Se activează..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro/strings.xml"
+ line="308"
+ column="94"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Укључује се..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr/strings.xml"
+ line="308"
+ column="94"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Inawasha..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw/strings.xml"
+ line="308"
+ column="94"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"กำลังเปิด..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th/strings.xml"
+ line="308"
+ column="94"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_wifi_secondary_label_transient" msgid="7501659015509357887">"Iyavula..."</string>"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu/strings.xml"
+ line="308"
+ column="94"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Connecting..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rCA/strings.xml"
+ line="318"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Connecting..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rXC/strings.xml"
+ line="318"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Łączę..."</string>"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pl/strings.xml"
+ line="318"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"በማገናኘት ላይ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"جارٍ الاتصال..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ar/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"সংযোগ কৰি থকা হৈছে..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-as/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Qoşulur..."</string>"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-az/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Povezuje se..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Падлучэнне..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-be/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Установява се връзка..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"সংযুক্ত হচ্ছে..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bn/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Povezivanje..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bs/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"S\'està connectant..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ca/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Připojování..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-cs/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Connecting..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rAU/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Connecting..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rGB/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Connecting..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-en-rIN/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Conectando..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-es/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Ühenduse loomine ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-et/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"در حال اتصال..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fa/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Connexion en cours..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-fr/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Conectando..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gl/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"કનેક્ટ કરી રહ્યું છે..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-gu/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"कनेक्ट हो रहा है..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hi/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Povezivanje..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hr/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Միանում է..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-hy/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Menghubungkan..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-in/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Tengist..."</string>"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-is/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Connessione in corso..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-it/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"מתבצע חיבור..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-iw/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"接続しています..."</string>"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ja/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"დაკავშირება..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ka/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"កំពុងតភ្ជាប់..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-km/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"ಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kn/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"연결 중..."</string>"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"ກຳລັງເຊື່ອມຕໍ່..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lo/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Prisijungiama..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lt/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Се поврзува..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mk/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"കണക്റ്റുചെയ്യുന്നു..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ml/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Холбогдож байна..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mn/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"कनेक्ट करत आहे..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-mr/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Menyambung..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ms/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"ဆက်သွယ်နေ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-my/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"कनेक्ट गरिँदै छ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ne/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"ସଂଯୋଗ କରୁଛି..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-or/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"ਕਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pa/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Conectando..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rBR/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"A ligar..."</string>"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Conectando..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Se conectează..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Соединение..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ru/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"සම්බන්ධ වෙමින්..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-si/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Pripája sa..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sk/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Vzpostavljanje povezave ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sl/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Po lidhet..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sq/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Повезује се..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Ansluter ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sv/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Inaunganisha..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"இணைக்கிறது..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ta/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"కనెక్ట్ అవుతోంది..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-te/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"กำลังเชื่อมต่อ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Kumokonekta..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tl/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Bağlanılıyor..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-tr/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Đang kết nối..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-vi/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"連線中..."</string>"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zh-rTW/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting" msgid="2381969772953268809">"Iyaxhuma..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu/strings.xml"
+ line="323"
+ column="74"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"በማብራት ላይ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-am/strings.xml"
+ line="325"
+ column="97"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Aktiv edilir..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-az/strings.xml"
+ line="325"
+ column="97"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Uključuje se..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-b+sr+Latn/strings.xml"
+ line="325"
+ column="97"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Включва се..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-bg/strings.xml"
+ line="325"
+ column="97"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"កំពុងបើក..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-km/strings.xml"
+ line="325"
+ column="97"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"ಆನ್ ಮಾಡಲಾಗುತ್ತಿದೆ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kn/strings.xml"
+ line="325"
+ column="97"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"켜는 중..."</string>"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ko/strings.xml"
+ line="325"
+ column="97"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"ກຳລັງເປີດ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-lo/strings.xml"
+ line="325"
+ column="97"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"A ativar..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-pt-rPT/strings.xml"
+ line="325"
+ column="97"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Se activează..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ro/strings.xml"
+ line="325"
+ column="97"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Укључује се..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sr/strings.xml"
+ line="325"
+ column="97"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Inawasha..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-sw/strings.xml"
+ line="325"
+ column="97"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"กำลังเปิด..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-th/strings.xml"
+ line="325"
+ column="97"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Iyavula..."</string>"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-zu/strings.xml"
+ line="325"
+ column="97"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="media_output_label_title" msgid="872824698593182505">"<xliff:g id="LABEL">%s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಆಗು..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-kn/strings.xml"
+ line="628"
+ column="94"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="quick_settings_connecting">Connecting...</string>"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values/strings.xml"
+ line="793"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="TypographyEllipsis"
+ message="Replace "..." with ellipsis character (…, &#8230;) ?"
+ errorLine1=" <string name="shutdown_progress" msgid="5464239146561542178">"सट डाउन गरिँदै छ..."</string>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/values-ne/strings.xml"
+ line="878"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="IconDipSize"
+ message="The image `ic_sysbar_lights_out_dot_small.png` varies significantly in its density-independent (dip) size across the various density versions: drawable-hdpi/ic_sysbar_lights_out_dot_small.png: 5x4 dp (7x6 px), drawable-mdpi/ic_sysbar_lights_out_dot_small.png: 8x9 dp (8x9 px), drawable-xhdpi/ic_sysbar_lights_out_dot_small.png: 6x7 dp (11x13 px), drawable-xxhdpi/ic_sysbar_lights_out_dot_small.png: 4x4 dp (13x12 px)">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_lights_out_dot_small.png"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable-hdpi/ic_sysbar_lights_out_dot_small.png"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_lights_out_dot_small.png"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable-mdpi/ic_sysbar_lights_out_dot_small.png"/>
+ </issue>
+
+ <issue
+ id="IconDipSize"
+ message="The image `ic_sysbar_lights_out_dot_small.png` varies significantly in its density-independent (dip) size across the various density versions: drawable-sw600dp-hdpi/ic_sysbar_lights_out_dot_small.png: 6x5 dp (9x8 px), drawable-sw600dp-mdpi/ic_sysbar_lights_out_dot_small.png: 7x10 dp (7x10 px), drawable-sw600dp-xhdpi/ic_sysbar_lights_out_dot_small.png: 7x8 dp (14x15 px), drawable-sw600dp-xxhdpi/ic_sysbar_lights_out_dot_small.png: 5x5 dp (15x15 px)">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable-sw600dp-xxhdpi/ic_sysbar_lights_out_dot_small.png"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable-sw600dp-hdpi/ic_sysbar_lights_out_dot_small.png"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable-sw600dp-xhdpi/ic_sysbar_lights_out_dot_small.png"/>
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable-sw600dp-mdpi/ic_sysbar_lights_out_dot_small.png"/>
+ </issue>
+
+ <issue
+ id="IconDensities"
+ message="Missing the following drawables in `drawable-hdpi`: dream_preview_back_arrow.png (found in drawable-mdpi, drawable-xhdpi, drawable-xxhdpi)">
+ <location
+ file="frameworks/base/packages/SystemUI/res/drawable-hdpi"/>
+ </issue>
+
+ <issue
+ id="ButtonOrder"
+ message="Cancel button should be on the left (was "Cancel | | Confirm | "Try again"", should be "Cancel | | | Confirm | "Try again"")"
+ errorLine1=" <Button android:id="@+id/button_cancel""
+ errorLine2=" ~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/biometric_prompt_layout.xml"
+ line="156"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="TextFields"
+ message="This text field does not specify an `inputType`"
+ errorLine1=" <EditText"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/clipboard_edit_text_activity.xml"
+ line="46"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="TextFields"
+ message="This text field does not specify an `inputType`"
+ errorLine1=" <EditText"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_output_broadcast_update_dialog.xml"
+ line="24"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`TouchHandler#onTouch` should call `View#performClick` when a click is detected"
+ errorLine1=" override fun onTouch(v: View, ev: MotionEvent): Boolean {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ui/viewbinder/ActivatableNotificationViewBinder.kt"
+ line="74"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`TouchHandler#onTouch` should call `View#performClick` when a click is detected"
+ errorLine1=" public boolean onTouch(View v, MotionEvent ev) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java"
+ line="71"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `CaptionsToggleImageButton` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/CaptionsToggleImageButton.java"
+ line="53"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``NotificationShadeWindowView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" getNotificationShadeWindowView().setOnTouchListener(getStatusBarWindowTouchListener());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+ line="1158"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` lambda should call `View#performClick` when a click is detected"
+ errorLine1=" return (v, event) -> {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java"
+ line="1477"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `ClipboardView` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent ev) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/tuner/ClipboardView.java"
+ line="53"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `CropView` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/scroll/CropView.java"
+ line="165"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`SwipeDismissHandler#onTouch` should call `View#performClick` when a click is detected"
+ errorLine1=" public boolean onTouch(View view, MotionEvent event) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/screenshot/DraggableConstraintLayout.java"
+ line="232"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `EmergencyButton` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java"
+ line="75"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``EmergencyButton`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mEmergencyButton.setOnTouchListener(new OnTouchListener(){"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java"
+ line="47"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` should call `View#performClick` when a click is detected"
+ errorLine1=" public boolean onTouch(View v, MotionEvent event) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/EmergencyCarrierArea.java"
+ line="49"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `ExpandableNotificationRow` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java"
+ line="987"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` lambda should call `View#performClick` when a click is detected"
+ errorLine1=" mContainer.setOnTouchListener((v, event) -> {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java"
+ line="2450"
+ column="43"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `ClingWindowView` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent motion) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/ImmersiveModeConfirmation.java"
+ line="479"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` should call `View#performClick` when a click is detected"
+ errorLine1=" public boolean onTouch(View v, MotionEvent event) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/Interaction.java"
+ line="29"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `KeyButtonView` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent ev) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonView.java"
+ line="267"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `KeyguardPatternView` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent ev) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java"
+ line="241"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``LockPatternView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mLockPatternView.setOnTouchListener((v, event) -> {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java"
+ line="229"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` lambda should call `View#performClick` when a click is detected"
+ errorLine1=" mLockPatternView.setOnTouchListener((v, event) -> {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java"
+ line="229"
+ column="45"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``LockPatternView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mLockPatternView.setOnTouchListener(null);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java"
+ line="258"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` lambda should call `View#performClick` when a click is detected"
+ errorLine1=" private final OnTouchListener mActionButtonTouchListener = (v, event) -> {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java"
+ line="60"
+ column="64"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``NumPadKey`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" button.setOnTouchListener((v, event) -> {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java"
+ line="97"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` lambda should call `View#performClick` when a click is detected"
+ errorLine1=" button.setOnTouchListener((v, event) -> {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java"
+ line="97"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``NumPadKey`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" button.setOnTouchListener(null);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputViewController.java"
+ line="175"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `KeyguardSecurityContainer` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java"
+ line="503"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `KeyguardSecurityViewFlipper` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent ev) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipper.java"
+ line="55"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``KeyguardUserSwitcherView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mView.setOnTouchListener((v, event) -> {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java"
+ line="190"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` lambda should call `View#performClick` when a click is detected"
+ errorLine1=" mView.setOnTouchListener((v, event) -> {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java"
+ line="190"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``ListView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" listView.setOnTouchListener((v, ev) -> {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherPopupMenu.java"
+ line="77"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` lambda should call `View#performClick` when a click is detected"
+ errorLine1=" listView.setOnTouchListener((v, ev) -> {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherPopupMenu.java"
+ line="77"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mImageView.setOnTouchListener(this::onTouch);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java"
+ line="117"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``MediaOutputSeekbar`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mSeekBar.setOnTouchListener((v, event) -> true);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+ line="509"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` lambda should call `View#performClick` when a click is detected"
+ errorLine1=" mSeekBar.setOnTouchListener((v, event) -> true);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+ line="509"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``MediaOutputSeekbar`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mSeekBar.setOnTouchListener((v, event) -> false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+ line="515"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` lambda should call `View#performClick` when a click is detected"
+ errorLine1=" mSeekBar.setOnTouchListener((v, event) -> false);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+ line="515"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``FrameLayout`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mIconAreaLayout.setOnTouchListener(((iconV, event) -> false));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+ line="522"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` lambda should call `View#performClick` when a click is detected"
+ errorLine1=" mIconAreaLayout.setOnTouchListener(((iconV, event) -> false));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+ line="522"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``FrameLayout`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mIconAreaLayout.setOnTouchListener(((iconV, event) -> {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+ line="528"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` lambda should call `View#performClick` when a click is detected"
+ errorLine1=" mIconAreaLayout.setOnTouchListener(((iconV, event) -> {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java"
+ line="528"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `MediaScrollView` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" override fun onTouchEvent(ev: MotionEvent?): Boolean {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaScrollView.kt"
+ line="106"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``NavigationBarView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mView.setOnTouchListener(this::onNavigationTouch);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java"
+ line="782"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `NavigationBarView` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java"
+ line="383"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `NearestTouchFrame` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/NearestTouchFrame.java"
+ line="207"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `NonInterceptingScrollView` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent ev) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/NonInterceptingScrollView.java"
+ line="46"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``FrameLayout`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" super.setOnTouchListener(touchHandler);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java"
+ line="111"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`TouchHandler#onTouch` should call `View#performClick` when a click is detected"
+ errorLine1=" public boolean onTouch(View v, MotionEvent event) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java"
+ line="5018"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `NotificationShadeWindowView` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent ev) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java"
+ line="133"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `NotificationStackScrollLayout` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent ev) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java"
+ line="3365"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `NumPadButton` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/NumPadButton.java"
+ line="84"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `NumPadKey` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/NumPadKey.java"
+ line="164"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `ObservableScrollView` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent ev) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/ObservableScrollView.java"
+ line="70"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `PhoneStatusBarView` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java"
+ line="208"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`QSContainerImpl#performClick` should call `super#performClick`"
+ errorLine1=" public boolean performClick() {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java"
+ line="106"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` should call `View#performClick` when a click is detected"
+ errorLine1=" public boolean onTouch(View v, MotionEvent event) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java"
+ line="52"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``NonInterceptingScrollView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mQSPanelContainer.setOnTouchListener(null);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java"
+ line="84"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``NonInterceptingScrollView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mQSPanelContainer.setOnTouchListener(mContainerTouchHandler);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java"
+ line="97"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``NonInterceptingScrollView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mQSPanelContainer.setOnTouchListener(null);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java"
+ line="105"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` should call `View#performClick` when a click is detected"
+ errorLine1=" public boolean onTouch(View v, MotionEvent event) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java"
+ line="77"
+ column="24"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``PagedTileLayout`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" pagedTileLayout.setOnTouchListener(mTileLayoutTouchListener);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java"
+ line="143"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `QSScrollLayout` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent ev) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSScrollLayout.java"
+ line="77"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `QuickStatusBarHeader` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java"
+ line="74"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `RemoteInputView` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java"
+ line="409"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``SeekBar`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" bar.setOnTouchListener(SeekBarTouchListener(this, bar))"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt"
+ line="348"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`SeekBarTouchListener#onTouch` should call `View#performClick` when a click is detected"
+ errorLine1=" override fun onTouch(view: View, event: MotionEvent): Boolean {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/media/controls/ui/viewmodel/SeekBarViewModel.kt"
+ line="456"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `SettingsButton` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java"
+ line="63"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`SimpleMirrorWindowControl#onTouch` should call `View#performClick` when a click is detected"
+ errorLine1=" public boolean onTouch(View v, MotionEvent event) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/SimpleMirrorWindowControl.java"
+ line="119"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `ToggleSeekBar` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSeekBar.java"
+ line="43"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `WalletView` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java"
+ line="138"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` lambda should call `View#performClick` when a click is detected"
+ errorLine1=" final View.OnTouchListener filterTouchListener = (View v, MotionEvent event) -> {"
+ errorLine2=" ^">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingActivity.java"
+ line="106"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``Button`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mAlert.getButton(BUTTON_POSITIVE).setOnTouchListener(filterTouchListener);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingActivity.java"
+ line="121"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mDragView.setOnTouchListener(this);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+ line="1015"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mCloseView.setOnTouchListener(this);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+ line="1020"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mTopLeftCornerView.setOnTouchListener(this);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+ line="1021"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mTopRightCornerView.setOnTouchListener(this);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+ line="1022"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mBottomLeftCornerView.setOnTouchListener(this);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+ line="1023"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mBottomRightCornerView.setOnTouchListener(this);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+ line="1024"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`WindowMagnificationController#onTouch` should call `View#performClick` when a click is detected"
+ errorLine1=" public boolean onTouch(View v, MotionEvent event) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java"
+ line="1172"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``LinearLayout`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mSettingView.setOnTouchListener(this::onTouch);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java"
+ line="516"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/alert_dialog_title_systemui.xml"
+ line="38"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/auth_biometric_background.xml"
+ line="26"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/bindable_status_bar_icon.xml"
+ line="25"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/biometric_prompt_layout.xml"
+ line="23"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/bluetooth_device_item.xml"
+ line="28"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/bluetooth_device_item.xml"
+ line="85"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/bluetooth_tile_dialog.xml"
+ line="170"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/broadcast_dialog.xml"
+ line="29"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/chipbar.xml"
+ line="65"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/chipbar.xml"
+ line="75"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/clipboard_overlay.xml"
+ line="27"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/clipboard_overlay.xml"
+ line="138"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/clipboard_overlay.xml"
+ line="143"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/clipboard_overlay.xml"
+ line="177"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/connected_device_signal.xml"
+ line="33"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/connected_display_chip.xml"
+ line="39"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/contrast_dialog.xml"
+ line="41"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/contrast_dialog.xml"
+ line="73"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/contrast_dialog.xml"
+ line="105"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/controls_app_item.xml"
+ line="35"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/controls_base_item.xml"
+ line="30"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/controls_base_item.xml"
+ line="115"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+ line="40"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/fgs_manager_app_item.xml"
+ line="25"
+ column="4"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/global_actions_grid_item_lite.xml"
+ line="25"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml"
+ line="32"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/global_actions_power_item.xml"
+ line="25"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/global_actions_view.xml"
+ line="43"
+ column="8"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/hybrid_conversation_notification.xml"
+ line="30"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/immersive_mode_cling.xml"
+ line="29"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/immersive_mode_cling.xml"
+ line="36"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/immersive_mode_cling.xml"
+ line="43"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+ line="104"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+ line="138"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+ line="264"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+ line="295"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+ line="326"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_connectivity_dialog.xml"
+ line="369"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_list_item.xml"
+ line="36"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/internet_list_item.xml"
+ line="67"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml"
+ line="27"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1="<ImageView xmlns:android="http://schemas.android.com/apk/res/android""
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/keyboard_shortcuts_key_icon_view.xml"
+ line="18"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView android:id="@+id/multi_user_avatar""
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/keyguard_status_bar.xml"
+ line="55"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/log_access_user_consent_dialog_permission.xml"
+ line="41"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/long_screenshot.xml"
+ line="74"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/long_screenshot.xml"
+ line="92"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/long_screenshot.xml"
+ line="156"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/magnifier_controllers.xml"
+ line="29"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_output_broadcast_area.xml"
+ line="34"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_output_broadcast_area.xml"
+ line="41"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_output_broadcast_area.xml"
+ line="80"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_output_broadcast_area.xml"
+ line="112"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_output_broadcast_area.xml"
+ line="130"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_output_list_item.xml"
+ line="54"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_recommendation_view.xml"
+ line="20"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+ line="32"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+ line="138"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+ line="187"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+ line="230"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+ line="273"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+ line="299"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+ line="309"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+ line="319"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+ line="329"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_session_view.xml"
+ line="339"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/mobile_signal_group.xml"
+ line="31"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/mobile_signal_group.xml"
+ line="39"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/mobile_signal_group.xml"
+ line="48"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notif_half_shelf.xml"
+ line="53"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="69"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="77"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="85"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="232"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="283"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_conversation_info.xml"
+ line="335"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="39"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="180"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="231"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="283"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_snooze.xml"
+ line="44"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/ongoing_call_chip.xml"
+ line="39"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/overlay_action_chip.xml"
+ line="34"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+ line="38"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_space_initial_layout.xml"
+ line="43"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_space_placeholder_layout.xml"
+ line="50"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_space_tile_view.xml"
+ line="38"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_status_scrim_layout.xml"
+ line="21"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_status_scrim_layout.xml"
+ line="32"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_status_scrim_layout.xml"
+ line="36"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_status_scrim_layout.xml"
+ line="48"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_status_scrim_layout.xml"
+ line="52"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_empty_layout.xml"
+ line="24"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_empty.xml"
+ line="33"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_empty.xml"
+ line="59"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_with_content.xml"
+ line="36"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_with_content.xml"
+ line="42"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_with_content.xml"
+ line="103"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_large_with_content.xml"
+ line="124"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_empty.xml"
+ line="35"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_empty.xml"
+ line="39"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_with_content.xml"
+ line="49"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_with_content.xml"
+ line="55"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_with_content.xml"
+ line="83"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_medium_with_content.xml"
+ line="147"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_small.xml"
+ line="34"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_small.xml"
+ line="42"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_small_horizontal.xml"
+ line="34"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_small_horizontal.xml"
+ line="42"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_suppressed_layout.xml"
+ line="24"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_with_suppression_detail_content_horizontal.xml"
+ line="28"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_with_suppression_detail_content_vertical.xml"
+ line="33"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_with_suppression_detail_content_vertical.xml"
+ line="53"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_work_profile_quiet_layout.xml"
+ line="25"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView android:id="@+id/work_widget_badge_icon""
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_work_profile_quiet_layout.xml"
+ line="32"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_item.xml"
+ line="30"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_item.xml"
+ line="53"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/privacy_dialog_item_v2.xml"
+ line="71"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/qs_dialog_secondary_mobile_network.xml"
+ line="26"
+ column="3"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/qs_dialog_secondary_mobile_network.xml"
+ line="56"
+ column="3"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/qs_tile_side_icon.xml"
+ line="23"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/qs_user_detail_item.xml"
+ line="55"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/quick_settings_footer_dialog_parental_controls.xml"
+ line="30"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/remote_input.xml"
+ line="46"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/remote_input.xml"
+ line="54"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+ line="48"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+ line="55"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+ line="65"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+ line="91"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+ line="98"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+ line="108"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+ line="134"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+ line="141"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons.xml"
+ line="151"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+ line="44"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+ line="51"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+ line="61"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+ line="84"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+ line="91"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+ line="101"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+ line="125"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+ line="132"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_land.xml"
+ line="142"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+ line="44"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+ line="52"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+ line="63"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+ line="87"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+ line="95"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+ line="106"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+ line="130"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+ line="138"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_pinning_request_buttons_sea.xml"
+ line="149"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_record_dialog.xml"
+ line="43"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_record_dialog.xml"
+ line="69"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screen_record_dialog.xml"
+ line="103"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screenshot.xml"
+ line="31"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screenshot_shelf.xml"
+ line="83"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screenshot_shelf.xml"
+ line="102"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screenshot_shelf.xml"
+ line="113"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screenshot_static.xml"
+ line="23"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screenshot_static.xml"
+ line="95"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screenshot_static.xml"
+ line="114"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screenshot_static.xml"
+ line="125"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screenshot_work_profile_first_run.xml"
+ line="12"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/screenshot_work_profile_first_run.xml"
+ line="36"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/seekbar_with_icon_buttons.xml"
+ line="33"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/seekbar_with_icon_buttons.xml"
+ line="60"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/sensor_use_started_title.xml"
+ line="32"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/sensor_use_started_title.xml"
+ line="39"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/shelf_action_chip.xml"
+ line="28"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/status_bar.xml"
+ line="33"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView android:id="@+id/current_user_avatar""
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/status_bar_user_chip_container.xml"
+ line="28"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/status_bar_wifi_group_inner.xml"
+ line="34"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/status_bar_wifi_group_inner.xml"
+ line="42"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/text_toast.xml"
+ line="33"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/tuner_shortcut_item.xml"
+ line="26"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/tuner_widget_settings_switch.xml"
+ line="24"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/udfps_enroll_view.xml"
+ line="32"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/udfps_enroll_view.xml"
+ line="38"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/udfps_keyguard_view_internal.xml"
+ line="27"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/user_switcher_fullscreen_item.xml"
+ line="23"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/volume_ringer_drawer.xml"
+ line="65"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/volume_ringer_drawer.xml"
+ line="83"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/volume_ringer_drawer.xml"
+ line="101"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/volume_ringer_drawer.xml"
+ line="125"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/window_magnifier_view.xml"
+ line="116"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/window_magnifier_view.xml"
+ line="126"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" <ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/wireless_charging_layout.xml"
+ line="44"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="LabelFor"
+ message="Missing accessibility label: provide either a view with an `android:labelFor` that references this view or provide an `android:hint`"
+ errorLine1=" <EditText"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/clipboard_edit_text_activity.xml"
+ line="46"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="LabelFor"
+ message="Missing accessibility label: provide either a view with an `android:labelFor` that references this view or provide an `android:hint`"
+ errorLine1=" <EditText"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/controls_dialog_pin.xml"
+ line="24"
+ column="4"/>
+ </issue>
+
+ <issue
+ id="LabelFor"
+ message="Missing accessibility label: provide either a view with an `android:labelFor` that references this view or provide an `android:hint`"
+ errorLine1=" <EditText"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/media_output_broadcast_update_dialog.xml"
+ line="24"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="SetTextI18n"
+ message="Number formatting does not take into account locale settings. Consider using `String.format` instead."
+ errorLine1=" mDigitText.setText(Integer.toString(mDigit));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/keyguard/NumPadKey.java"
+ line="115"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="SetTextI18n"
+ message="Number formatting does not take into account locale settings. Consider using `String.format` instead."
+ errorLine1=" if (row.number != null) row.number.setText(Integer.toString(vlevel));"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java"
+ line="2026"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="HardcodedText"
+ message="Hardcoded string "Yes", should use `@string` resource"
+ errorLine1=" android:text="Yes""
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+ line="89"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="HardcodedText"
+ message="Hardcoded string "No", should use `@string` resource"
+ errorLine1=" android:text="No""
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/feedback_info.xml"
+ line="100"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="RelativeOverlap"
+ message="`@id/done` can overlap `@id/turn_off_notifications` if @string/inline_turn_off_notifications, @string/inline_ok_button grow due to localized text expansion"
+ errorLine1=" <TextView"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_info.xml"
+ line="342"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="RelativeOverlap"
+ message="`@id/undo` can overlap `@id/expand_button` if @string/snooze_undo grows due to localized text expansion"
+ errorLine1=" <TextView"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/notification_snooze.xml"
+ line="54"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="RelativeOverlap"
+ message="`@id/done` can overlap `@id/turn_off_notifications` if @string/inline_turn_off_notifications, @string/inline_done_button grow due to localized text expansion"
+ errorLine1=" <TextView"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/partial_conversation_info.xml"
+ line="156"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="RelativeOverlap"
+ message="`@id/punctuation3` can overlap `@id/punctuation4` if @id/punctuation4, @id/punctuation3 grow due to localized text expansion"
+ errorLine1=" <TextView"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_punctuation_background_large.xml"
+ line="53"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="RelativeOverlap"
+ message="`@id/punctuation5` can overlap `@id/punctuation1` if @id/punctuation1, @id/punctuation5 grow due to localized text expansion"
+ errorLine1=" <TextView"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_punctuation_background_large.xml"
+ line="81"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="RelativeOverlap"
+ message="`@id/punctuation5` can overlap `@id/punctuation2` if @id/punctuation2, @id/punctuation5 grow due to localized text expansion"
+ errorLine1=" <TextView"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_punctuation_background_large.xml"
+ line="81"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="RelativeOverlap"
+ message="`@id/punctuation5` can overlap `@id/punctuation6` if @id/punctuation6, @id/punctuation5 grow due to localized text expansion"
+ errorLine1=" <TextView"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="frameworks/base/packages/SystemUI/res/layout/people_tile_punctuation_background_large.xml"
+ line="81"
+ column="6"/>
+ </issue>
+
+</issues>
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index ed2d20c..aa70c45 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -18,7 +18,6 @@
package com.android.keyguard
import android.content.res.Configuration
-import android.hardware.biometrics.BiometricRequestConstants
import android.media.AudioManager
import android.telephony.TelephonyManager
import android.testing.TestableLooper.RunWithLooper
@@ -41,8 +40,6 @@
import com.android.systemui.Flags as AConfigFlags
import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.FaceAuthAccessibilityDelegate
-import com.android.systemui.biometrics.SideFpsController
-import com.android.systemui.biometrics.SideFpsUiRequestSource
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants
import com.android.systemui.classifier.FalsingA11yDelegate
@@ -70,7 +67,6 @@
import com.android.systemui.scene.shared.model.FakeSceneDataSource
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.DevicePostureController
import com.android.systemui.statusbar.policy.DeviceProvisionedController
@@ -87,7 +83,6 @@
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.settings.GlobalSettings
import com.google.common.truth.Truth
-import java.util.Optional
import junit.framework.Assert
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
@@ -143,7 +138,6 @@
@Mock private lateinit var userSwitcherController: UserSwitcherController
@Mock private lateinit var sessionTracker: SessionTracker
@Mock private lateinit var keyguardViewController: KeyguardViewController
- @Mock private lateinit var sideFpsController: SideFpsController
@Mock private lateinit var keyguardPasswordViewControllerMock: KeyguardPasswordViewController
@Mock private lateinit var falsingA11yDelegate: FalsingA11yDelegate
@Mock private lateinit var telephonyManager: TelephonyManager
@@ -214,9 +208,6 @@
mSetFlagsRule.enableFlags(
AConfigFlags.FLAG_REVAMPED_BOUNCER_MESSAGES,
)
- mSetFlagsRule.disableFlags(
- FLAG_SIDEFPS_CONTROLLER_REFACTOR,
- )
if (!SceneContainerFlag.isEnabled) {
mSetFlagsRule.disableFlags(
AConfigFlags.FLAG_KEYGUARD_WM_STATE_REFACTOR,
@@ -273,7 +264,6 @@
featureFlags,
globalSettings,
sessionTracker,
- Optional.of(sideFpsController),
falsingA11yDelegate,
telephonyManager,
viewMediatorCallback,
@@ -781,24 +771,6 @@
}
@Test
- fun sideFpsControllerShow() {
- mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
- underTest.updateSideFpsVisibility(/* isVisible= */ true)
- verify(sideFpsController)
- .show(
- SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricRequestConstants.REASON_AUTH_KEYGUARD
- )
- }
-
- @Test
- fun sideFpsControllerHide() {
- mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
- underTest.updateSideFpsVisibility(/* isVisible= */ false)
- verify(sideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER)
- }
-
- @Test
fun setExpansion_setsAlpha() {
underTest.setExpansion(KeyguardBouncerConstants.EXPANSION_VISIBLE)
verify(view).alpha = 1f
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java
index 04c4efb..fefe5a0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandlerTest.java
@@ -149,7 +149,6 @@
mUiEventLogger);
when(mScrimManager.getCurrentController()).thenReturn(mScrimController);
- when(mCentralSurfaces.isBouncerShowing()).thenReturn(false);
when(mValueAnimatorCreator.create(anyFloat(), anyFloat())).thenReturn(mValueAnimator);
when(mVelocityTrackerFactory.obtain()).thenReturn(mVelocityTracker);
when(mFlingAnimationUtils.getMinVelocityPxPerSecond()).thenReturn(Float.MAX_VALUE);
@@ -193,11 +192,6 @@
2)).isTrue();
}
- private enum Direction {
- DOWN,
- UP,
- }
-
@Test
public void testSwipeUp_whenBouncerInitiallyShowing_reduceHeightWithExclusionRects() {
mTouchHandler.getTouchInitiationRegion(SCREEN_BOUNDS, mRegion,
@@ -210,7 +204,7 @@
SCREEN_HEIGHT_PX * MIN_BOUNCER_HEIGHT;
final int minAllowableBottom = SCREEN_HEIGHT_PX - Math.round(minBouncerHeight);
- expected.set(0, minAllowableBottom , SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX);
+ expected.set(0, minAllowableBottom, SCREEN_WIDTH_PX, SCREEN_HEIGHT_PX);
assertThat(bounds).isEqualTo(expected);
@@ -278,69 +272,11 @@
}
/**
- * Makes sure swiping up when bouncer initially showing doesn't change the expansion amount.
- */
- @DisableFlags(Flags.FLAG_DREAM_OVERLAY_BOUNCER_SWIPE_DIRECTION_FILTERING)
- @Test
- public void testSwipeUp_whenBouncerInitiallyShowing_doesNotSetExpansion() {
- when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
-
- mTouchHandler.onSessionStart(mTouchSession);
- ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
- ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
- verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
-
- final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
-
- final float percent = .3f;
- final float distanceY = SCREEN_HEIGHT_PX * percent;
-
- // Swiping up near the top of the screen where the touch initiation region is.
- final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
- 0, distanceY, 0);
- final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
- 0, 0, 0);
-
- assertThat(gestureListener.onScroll(event1, event2, 0, distanceY)).isTrue();
-
- verify(mScrimController, never()).expand(any());
- }
-
- /**
- * Makes sure swiping up when bouncer initially showing doesn't change the expansion amount.
- */
- @Test
- @EnableFlags(Flags.FLAG_DREAM_OVERLAY_BOUNCER_SWIPE_DIRECTION_FILTERING)
- public void testSwipeUp_whenBouncerInitiallyShowing_doesNotSetExpansion_directionFiltering() {
- when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
-
- mTouchHandler.onSessionStart(mTouchSession);
- ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
- ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
- verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
-
- final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
-
- final float percent = .3f;
- final float distanceY = SCREEN_HEIGHT_PX * percent;
-
- // Swiping up near the top of the screen where the touch initiation region is.
- final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
- 0, distanceY, 0);
- final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
- 0, 0, 0);
-
- assertThat(gestureListener.onScroll(event1, event2, 0, distanceY)).isFalse();
-
- verify(mScrimController, never()).expand(any());
- }
-
- /**
- * Makes sure swiping down when bouncer initially hidden doesn't change the expansion amount.
+ * Makes sure swiping down doesn't change the expansion amount.
*/
@Test
@DisableFlags(Flags.FLAG_DREAM_OVERLAY_BOUNCER_SWIPE_DIRECTION_FILTERING)
- public void testSwipeDown_whenBouncerInitiallyHidden_doesNotSetExpansion() {
+ public void testSwipeDown_doesNotSetExpansion() {
mTouchHandler.onSessionStart(mTouchSession);
ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
@@ -401,34 +337,8 @@
final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
- verifyScroll(.3f, Direction.UP, false, gestureListener);
-
- // Ensure that subsequent gestures are treated as expanding even if the bouncer state
- // changes.
- when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
- verifyScroll(.7f, Direction.UP, false, gestureListener);
- }
-
- /**
- * Makes sure the expansion amount is proportional to scroll.
- */
- @Test
- public void testSwipeDown_setsCorrectExpansionAmount() {
- when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
-
- mTouchHandler.onSessionStart(mTouchSession);
- ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
- ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
- verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
-
- final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
-
- verifyScroll(.3f, Direction.DOWN, true, gestureListener);
-
- // Ensure that subsequent gestures are treated as collapsing even if the bouncer state
- // changes.
- when(mCentralSurfaces.isBouncerShowing()).thenReturn(false);
- verifyScroll(.7f, Direction.DOWN, true, gestureListener);
+ verifyScroll(.3f, gestureListener);
+ verifyScroll(.7f, gestureListener);
}
/**
@@ -493,25 +403,24 @@
verify(mCentralSurfaces, never()).awakenDreams();
}
- private void verifyScroll(float percent, Direction direction,
- boolean isBouncerInitiallyShowing, GestureDetector.OnGestureListener gestureListener) {
+ private void verifyScroll(float percent,
+ OnGestureListener gestureListener) {
final float distanceY = SCREEN_HEIGHT_PX * percent;
final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
- 0, direction == Direction.UP ? SCREEN_HEIGHT_PX : 0, 0);
+ 0, SCREEN_HEIGHT_PX, 0);
final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
- 0, direction == Direction.UP ? SCREEN_HEIGHT_PX - distanceY : distanceY, 0);
+ 0, SCREEN_HEIGHT_PX - distanceY, 0);
reset(mScrimController);
assertThat(gestureListener.onScroll(event1, event2, 0,
- direction == Direction.UP ? distanceY : -distanceY))
+ distanceY))
.isTrue();
// Ensure only called once
verify(mScrimController).expand(any());
- final float expansion = isBouncerInitiallyShowing ? percent : 1 - percent;
- final float dragDownAmount = event2.getY() - event1.getY();
+ final float expansion = 1 - percent;
// Ensure correct expansion passed in.
ShadeExpansionChangeEvent event =
@@ -529,7 +438,7 @@
final float expansion = 1 - swipeUpPercentage;
// The upward velocity is ignored.
final float velocityY = -1;
- swipeToPosition(swipeUpPercentage, Direction.UP, velocityY);
+ swipeToPosition(swipeUpPercentage, velocityY);
verify(mValueAnimatorCreator).create(eq(expansion),
eq(KeyguardBouncerConstants.EXPANSION_HIDDEN));
@@ -552,7 +461,7 @@
final float expansion = 1 - swipeUpPercentage;
// The downward velocity is ignored.
final float velocityY = 1;
- swipeToPosition(swipeUpPercentage, Direction.UP, velocityY);
+ swipeToPosition(swipeUpPercentage, velocityY);
verify(mValueAnimatorCreator).create(eq(expansion),
eq(KeyguardBouncerConstants.EXPANSION_VISIBLE));
@@ -573,57 +482,6 @@
}
/**
- * Tests that ending a downward swipe above the set threshold will continue the expansion,
- * but will not trigger logging of the DREAM_SWIPED event.
- */
- @Test
- public void testSwipeDownPositionAboveThreshold_expandsBouncer_doesNotLog() {
- when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
-
- final float swipeDownPercentage = .3f;
- // The downward velocity is ignored.
- final float velocityY = 1;
- swipeToPosition(swipeDownPercentage, Direction.DOWN, velocityY);
-
- verify(mValueAnimatorCreator).create(eq(swipeDownPercentage),
- eq(KeyguardBouncerConstants.EXPANSION_VISIBLE));
- verify(mValueAnimator, never()).addListener(any());
-
- verify(mFlingAnimationUtils).apply(eq(mValueAnimator),
- eq(SCREEN_HEIGHT_PX * swipeDownPercentage),
- eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_VISIBLE),
- eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
- verify(mValueAnimator).start();
- verify(mUiEventLogger, never()).log(any());
- }
-
- /**
- * Tests that swiping down with a speed above the set threshold leads to bouncer collapsing
- * down.
- */
- @Test
- public void testSwipeDownVelocityAboveMin_collapsesBouncer() {
- when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
- when(mFlingAnimationUtils.getMinVelocityPxPerSecond()).thenReturn((float) 0);
-
- // The ending position above the set threshold is ignored.
- final float swipeDownPercentage = .3f;
- final float velocityY = 1;
- swipeToPosition(swipeDownPercentage, Direction.DOWN, velocityY);
-
- verify(mValueAnimatorCreator).create(eq(swipeDownPercentage),
- eq(KeyguardBouncerConstants.EXPANSION_HIDDEN));
- verify(mValueAnimator, never()).addListener(any());
-
- verify(mFlingAnimationUtilsClosing).apply(eq(mValueAnimator),
- eq(SCREEN_HEIGHT_PX * swipeDownPercentage),
- eq(SCREEN_HEIGHT_PX * KeyguardBouncerConstants.EXPANSION_HIDDEN),
- eq(velocityY), eq((float) SCREEN_HEIGHT_PX));
- verify(mValueAnimator).start();
- verify(mUiEventLogger, never()).log(any());
- }
-
- /**
* Tests that swiping up with a speed above the set threshold will continue the expansion.
*/
@Test
@@ -634,7 +492,7 @@
final float swipeUpPercentage = .3f;
final float expansion = 1 - swipeUpPercentage;
final float velocityY = -1;
- swipeToPosition(swipeUpPercentage, Direction.UP, velocityY);
+ swipeToPosition(swipeUpPercentage, velocityY);
verify(mValueAnimatorCreator).create(eq(expansion),
eq(KeyguardBouncerConstants.EXPANSION_VISIBLE));
@@ -654,26 +512,6 @@
verify(mUiEventLogger).log(BouncerSwipeTouchHandler.DreamEvent.DREAM_BOUNCER_FULLY_VISIBLE);
}
- /**
- * Ensures {@link CentralSurfaces}
- */
- @Test
- public void testInformBouncerShowingOnExpand() {
- swipeToPosition(1f, Direction.UP, 0);
- }
-
- /**
- * Ensures {@link CentralSurfaces}
- */
- @Test
- public void testInformBouncerHidingOnCollapse() {
- // Must swipe up to set initial state.
- swipeToPosition(1f, Direction.UP, 0);
- Mockito.clearInvocations(mCentralSurfaces);
-
- swipeToPosition(0f, Direction.DOWN, 0);
- }
-
@Test
public void testTouchSessionOnRemovedCalledTwice() {
mTouchHandler.onSessionStart(mTouchSession);
@@ -684,7 +522,7 @@
onRemovedCallbackCaptor.getValue().onRemoved();
}
- private void swipeToPosition(float percent, Direction direction, float velocityY) {
+ private void swipeToPosition(float percent, float velocityY) {
Mockito.clearInvocations(mTouchSession);
mTouchHandler.onSessionStart(mTouchSession);
ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
@@ -699,12 +537,12 @@
final float distanceY = SCREEN_HEIGHT_PX * percent;
final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
- 0, direction == Direction.UP ? SCREEN_HEIGHT_PX : 0, 0);
+ 0, SCREEN_HEIGHT_PX, 0);
final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
- 0, direction == Direction.UP ? SCREEN_HEIGHT_PX - distanceY : distanceY, 0);
+ 0, SCREEN_HEIGHT_PX - distanceY, 0);
assertThat(gestureListenerCaptor.getValue().onScroll(event1, event2, 0,
- direction == Direction.UP ? distanceY : -distanceY))
+ distanceY))
.isTrue();
final MotionEvent upEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.java
index 27bffd0..11a4241 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/ambient/touch/ShadeTouchHandlerTest.java
@@ -18,8 +18,10 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.view.GestureDetector;
import android.view.MotionEvent;
@@ -28,7 +30,6 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.shade.ShadeViewController;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.statusbar.phone.CentralSurfaces;
@@ -36,6 +37,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
@@ -49,66 +51,89 @@
CentralSurfaces mCentralSurfaces;
@Mock
- ShadeViewController mShadeViewController;
-
- @Mock
TouchHandler.TouchSession mTouchSession;
ShadeTouchHandler mTouchHandler;
+ @Captor
+ ArgumentCaptor<GestureDetector.OnGestureListener> mGestureListenerCaptor;
+ @Captor
+ ArgumentCaptor<InputChannelCompat.InputEventListener> mInputListenerCaptor;
+
private static final int TOUCH_HEIGHT = 20;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mTouchHandler = new ShadeTouchHandler(Optional.of(mCentralSurfaces), mShadeViewController,
- TOUCH_HEIGHT);
+
+ mTouchHandler = new ShadeTouchHandler(Optional.of(mCentralSurfaces), TOUCH_HEIGHT);
+ }
+
+ // Verifies that a swipe down in the gesture region is captured by the shade touch handler.
+ @Test
+ public void testSwipeDown_captured() {
+ final boolean captured = swipe(Direction.DOWN);
+
+ assertThat(captured).isTrue();
+ }
+
+ // Verifies that a swipe in the upward direction is not catpured.
+ @Test
+ public void testSwipeUp_notCaptured() {
+ final boolean captured = swipe(Direction.UP);
+
+ // Motion events not captured as the swipe is going in the wrong direction.
+ assertThat(captured).isFalse();
+ }
+
+ // Verifies that a swipe down forwards captured touches to the shade window for handling.
+ @Test
+ public void testSwipeDown_sentToShadeWindow() {
+ swipe(Direction.DOWN);
+
+ // Both motion events are sent for the shade window to process.
+ verify(mCentralSurfaces, times(2)).handleExternalShadeWindowTouch(any());
+ }
+
+ // Verifies that a swipe down is not forwarded to the shade window.
+ @Test
+ public void testSwipeUp_touchesNotSent() {
+ swipe(Direction.UP);
+
+ // Motion events are not sent for the shade window to process as the swipe is going in the
+ // wrong direction.
+ verify(mCentralSurfaces, never()).handleExternalShadeWindowTouch(any());
}
/**
- * Verify that touches aren't handled when the bouncer is showing.
+ * Simulates a swipe in the given direction and returns true if the touch was intercepted by the
+ * touch handler's gesture listener.
+ * <p>
+ * Swipe down starts from a Y coordinate of 0 and goes downward. Swipe up starts from the edge
+ * of the gesture region, {@link #TOUCH_HEIGHT}, and goes upward to 0.
*/
- @Test
- public void testInactiveOnBouncer() {
- when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
+ private boolean swipe(Direction direction) {
+ Mockito.clearInvocations(mTouchSession);
mTouchHandler.onSessionStart(mTouchSession);
- verify(mTouchSession).pop();
+
+ verify(mTouchSession).registerGestureListener(mGestureListenerCaptor.capture());
+ verify(mTouchSession).registerInputListener(mInputListenerCaptor.capture());
+
+ final float startY = direction == Direction.UP ? TOUCH_HEIGHT : 0;
+ final float endY = direction == Direction.UP ? 0 : TOUCH_HEIGHT;
+
+ // Send touches to the input and gesture listener.
+ final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, startY, 0);
+ final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, endY, 0);
+ mInputListenerCaptor.getValue().onInputEvent(event1);
+ mInputListenerCaptor.getValue().onInputEvent(event2);
+ final boolean captured = mGestureListenerCaptor.getValue().onScroll(event1, event2, 0,
+ startY - endY);
+
+ return captured;
}
- /**
- * Make sure {@link ShadeTouchHandler}
- */
- @Test
- public void testTouchPilferingOnScroll() {
- final MotionEvent motionEvent1 = Mockito.mock(MotionEvent.class);
- final MotionEvent motionEvent2 = Mockito.mock(MotionEvent.class);
-
- final ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerArgumentCaptor =
- ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
-
- mTouchHandler.onSessionStart(mTouchSession);
- verify(mTouchSession).registerGestureListener(gestureListenerArgumentCaptor.capture());
-
- assertThat(gestureListenerArgumentCaptor.getValue()
- .onScroll(motionEvent1, motionEvent2, 1, 1))
- .isTrue();
+ private enum Direction {
+ DOWN, UP,
}
-
- /**
- * Ensure touches are propagated to the {@link ShadeViewController}.
- */
- @Test
- public void testEventPropagation() {
- final MotionEvent motionEvent = Mockito.mock(MotionEvent.class);
-
- final ArgumentCaptor<InputChannelCompat.InputEventListener>
- inputEventListenerArgumentCaptor =
- ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
-
- mTouchHandler.onSessionStart(mTouchSession);
- verify(mTouchSession).registerInputListener(inputEventListenerArgumentCaptor.capture());
- inputEventListenerArgumentCaptor.getValue().onInputEvent(motionEvent);
- verify(mShadeViewController).handleExternalTouch(motionEvent);
- }
-
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
index 289896e01..f4ad764 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -145,8 +145,6 @@
@Mock
private UdfpsController mUdfpsController;
@Mock
- private SideFpsController mSideFpsController;
- @Mock
private DisplayManager mDisplayManager;
@Mock
private WakefulnessLifecycle mWakefulnessLifecycle;
@@ -1064,14 +1062,12 @@
TestableAuthController(Context context) {
super(context, null /* applicationCoroutineScope */,
mExecution, mCommandQueue, mActivityTaskManager, mWindowManager,
- mFingerprintManager, mFaceManager, () -> mUdfpsController,
- () -> mSideFpsController, mDisplayManager, mWakefulnessLifecycle,
- mPanelInteractionDetector, mUserManager, mLockPatternUtils, () -> mUdfpsLogger,
- () -> mLogContextInteractor,
- () -> mBiometricPromptCredentialInteractor,
- () -> mPromptSelectionInteractor, () -> mCredentialViewModel,
- () -> mPromptViewModel, mInteractionJankMonitor, mHandler, mBackgroundExecutor,
- mUdfpsUtils, mVibratorHelper);
+ mFingerprintManager, mFaceManager, () -> mUdfpsController, mDisplayManager,
+ mWakefulnessLifecycle, mPanelInteractionDetector, mUserManager,
+ mLockPatternUtils, () -> mUdfpsLogger, () -> mLogContextInteractor,
+ () -> mBiometricPromptCredentialInteractor, () -> mPromptSelectionInteractor,
+ () -> mCredentialViewModel, () -> mPromptViewModel, mInteractionJankMonitor,
+ mHandler, mBackgroundExecutor, mUdfpsUtils, mVibratorHelper);
}
@Override
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
deleted file mode 100644
index 07e9815..0000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/SideFpsControllerTest.kt
+++ /dev/null
@@ -1,898 +0,0 @@
-/*
- * Copyright (C) 2021 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.biometrics
-
-import android.animation.Animator
-import android.app.ActivityManager
-import android.app.ActivityTaskManager
-import android.content.ComponentName
-import android.graphics.Insets
-import android.graphics.Rect
-import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_KEYGUARD
-import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_SETTINGS
-import android.hardware.biometrics.BiometricRequestConstants.REASON_UNKNOWN
-import android.hardware.biometrics.SensorLocationInternal
-import android.hardware.biometrics.SensorProperties
-import android.hardware.display.DisplayManager
-import android.hardware.display.DisplayManagerGlobal
-import android.hardware.fingerprint.FingerprintManager
-import android.hardware.fingerprint.FingerprintSensorProperties
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
-import android.hardware.fingerprint.ISidefpsController
-import android.os.Handler
-import android.testing.TestableLooper
-import android.view.Display
-import android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS
-import android.view.DisplayInfo
-import android.view.LayoutInflater
-import android.view.Surface
-import android.view.View
-import android.view.ViewPropertyAnimator
-import android.view.WindowInsets
-import android.view.WindowManager
-import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION
-import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
-import android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
-import android.view.WindowMetrics
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.airbnb.lottie.LottieAnimationView
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.SysuiTestableContext
-import com.android.systemui.biometrics.data.repository.FakeDisplayStateRepository
-import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
-import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
-import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl
-import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
-import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
-import com.android.systemui.display.data.repository.FakeDisplayRepository
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.res.R
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-import com.android.systemui.statusbar.policy.KeyguardStateController
-import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.time.FakeSystemClock
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.test.StandardTestDispatcher
-import kotlinx.coroutines.test.TestCoroutineScope
-import kotlinx.coroutines.test.TestScope
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers.eq
-import org.mockito.Captor
-import org.mockito.Mock
-import org.mockito.Mockito.any
-import org.mockito.Mockito.anyFloat
-import org.mockito.Mockito.anyInt
-import org.mockito.Mockito.anyLong
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.reset
-import org.mockito.Mockito.times
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenEver
-import org.mockito.junit.MockitoJUnit
-
-private const val DISPLAY_ID = 2
-private const val SENSOR_ID = 1
-
-private const val REAR_DISPLAY_MODE_DEVICE_STATE = 3
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-@TestableLooper.RunWithLooper
-class SideFpsControllerTest : SysuiTestCase() {
-
- @JvmField @Rule var rule = MockitoJUnit.rule()
-
- @Mock lateinit var layoutInflater: LayoutInflater
- @Mock lateinit var fingerprintManager: FingerprintManager
- @Mock lateinit var windowManager: WindowManager
- @Mock lateinit var activityTaskManager: ActivityTaskManager
- @Mock lateinit var sideFpsView: View
- @Mock lateinit var displayManager: DisplayManager
- @Mock lateinit var handler: Handler
- @Mock lateinit var dumpManager: DumpManager
- @Mock lateinit var fpsUnlockTracker: FpsUnlockTracker
- @Captor lateinit var overlayCaptor: ArgumentCaptor<View>
- @Captor lateinit var overlayViewParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>
-
- private lateinit var displayRepository: FakeDisplayRepository
- private lateinit var displayStateRepository: FakeDisplayStateRepository
- private lateinit var keyguardBouncerRepository: FakeKeyguardBouncerRepository
- private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
- private lateinit var displayStateInteractor: DisplayStateInteractor
-
- private val executor = FakeExecutor(FakeSystemClock())
- private val testScope = TestScope(StandardTestDispatcher())
-
- private lateinit var overlayController: ISidefpsController
- private lateinit var sideFpsController: SideFpsController
-
- enum class DeviceConfig {
- X_ALIGNED,
- Y_ALIGNED,
- }
-
- private lateinit var deviceConfig: DeviceConfig
- private lateinit var indicatorBounds: Rect
- private lateinit var displayBounds: Rect
- private lateinit var sensorLocation: SensorLocationInternal
- private var displayWidth: Int = 0
- private var displayHeight: Int = 0
- private var boundsWidth: Int = 0
- private var boundsHeight: Int = 0
-
- @Before
- fun setup() {
- mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
- displayRepository = FakeDisplayRepository()
- displayStateRepository = FakeDisplayStateRepository()
- keyguardBouncerRepository = FakeKeyguardBouncerRepository()
- alternateBouncerInteractor =
- AlternateBouncerInteractor(
- mock(StatusBarStateController::class.java),
- mock(KeyguardStateController::class.java),
- keyguardBouncerRepository,
- FakeFingerprintPropertyRepository(),
- FakeBiometricSettingsRepository(),
- FakeSystemClock(),
- mock(KeyguardUpdateMonitor::class.java),
- { mock(DeviceEntryFingerprintAuthInteractor::class.java) },
- { mock(KeyguardInteractor::class.java) },
- { mock(KeyguardTransitionInteractor::class.java) },
- testScope.backgroundScope,
- )
- displayStateInteractor =
- DisplayStateInteractorImpl(
- testScope.backgroundScope,
- context,
- executor,
- displayStateRepository,
- displayRepository,
- )
-
- context.addMockSystemService(DisplayManager::class.java, displayManager)
- context.addMockSystemService(WindowManager::class.java, windowManager)
-
- whenEver(layoutInflater.inflate(R.layout.sidefps_view, null, false)).thenReturn(sideFpsView)
- whenEver(sideFpsView.requireViewById<LottieAnimationView>(eq(R.id.sidefps_animation)))
- .thenReturn(mock(LottieAnimationView::class.java))
- with(mock(ViewPropertyAnimator::class.java)) {
- whenEver(sideFpsView.animate()).thenReturn(this)
- whenEver(alpha(anyFloat())).thenReturn(this)
- whenEver(setStartDelay(anyLong())).thenReturn(this)
- whenEver(setDuration(anyLong())).thenReturn(this)
- whenEver(setListener(any())).thenAnswer {
- (it.arguments[0] as Animator.AnimatorListener).onAnimationEnd(
- mock(Animator::class.java)
- )
- this
- }
- }
- }
-
- private fun testWithDisplay(
- deviceConfig: DeviceConfig = DeviceConfig.X_ALIGNED,
- isReverseDefaultRotation: Boolean = false,
- initInfo: DisplayInfo.() -> Unit = {},
- windowInsets: WindowInsets = insetsForSmallNavbar(),
- inRearDisplayMode: Boolean = false,
- block: () -> Unit
- ) {
- this.deviceConfig = deviceConfig
-
- when (deviceConfig) {
- DeviceConfig.X_ALIGNED -> {
- displayWidth = 3000
- displayHeight = 1500
- sensorLocation = SensorLocationInternal("", 2500, 0, 0)
- boundsWidth = 200
- boundsHeight = 100
- }
- DeviceConfig.Y_ALIGNED -> {
- displayWidth = 2500
- displayHeight = 2000
- sensorLocation = SensorLocationInternal("", 0, 300, 0)
- boundsWidth = 100
- boundsHeight = 200
- }
- }
-
- indicatorBounds = Rect(0, 0, boundsWidth, boundsHeight)
- displayBounds = Rect(0, 0, displayWidth, displayHeight)
- var locations = listOf(sensorLocation)
-
- whenEver(fingerprintManager.sensorPropertiesInternal)
- .thenReturn(
- listOf(
- FingerprintSensorPropertiesInternal(
- SENSOR_ID,
- SensorProperties.STRENGTH_STRONG,
- 5 /* maxEnrollmentsPerUser */,
- listOf() /* componentInfo */,
- FingerprintSensorProperties.TYPE_POWER_BUTTON,
- true /* halControlsIllumination */,
- true /* resetLockoutRequiresHardwareAuthToken */,
- locations
- )
- )
- )
-
- val displayInfo = DisplayInfo()
- displayInfo.initInfo()
-
- val dmGlobal = mock(DisplayManagerGlobal::class.java)
- val display = Display(dmGlobal, DISPLAY_ID, displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS)
-
- whenEver(dmGlobal.getDisplayInfo(eq(DISPLAY_ID))).thenReturn(displayInfo)
- whenEver(windowManager.defaultDisplay).thenReturn(display)
- whenEver(windowManager.maximumWindowMetrics)
- .thenReturn(WindowMetrics(displayBounds, WindowInsets.CONSUMED))
- whenEver(windowManager.currentWindowMetrics)
- .thenReturn(WindowMetrics(displayBounds, windowInsets))
-
- val sideFpsControllerContext = context.createDisplayContext(display) as SysuiTestableContext
- sideFpsControllerContext.orCreateTestableResources.addOverride(
- com.android.internal.R.bool.config_reverseDefaultRotation,
- isReverseDefaultRotation
- )
-
- val rearDisplayDeviceStates =
- if (inRearDisplayMode) intArrayOf(REAR_DISPLAY_MODE_DEVICE_STATE) else intArrayOf()
- sideFpsControllerContext.orCreateTestableResources.addOverride(
- com.android.internal.R.array.config_rearDisplayDeviceStates,
- rearDisplayDeviceStates
- )
-
- sideFpsController =
- SideFpsController(
- sideFpsControllerContext,
- layoutInflater,
- fingerprintManager,
- windowManager,
- activityTaskManager,
- displayManager,
- displayStateInteractor,
- executor,
- handler,
- alternateBouncerInteractor,
- TestCoroutineScope(),
- dumpManager,
- fpsUnlockTracker
- )
- displayStateRepository.setIsInRearDisplayMode(inRearDisplayMode)
-
- overlayController =
- ArgumentCaptor.forClass(ISidefpsController::class.java)
- .apply { verify(fingerprintManager).setSidefpsController(capture()) }
- .value
-
- block()
- }
-
- @Test
- fun testSubscribesToOrientationChangesWhenShowingOverlay() = testWithDisplay {
- overlayController.show(SENSOR_ID, REASON_UNKNOWN)
- executor.runAllReady()
-
- verify(displayManager).registerDisplayListener(any(), eq(handler), anyLong())
-
- overlayController.hide(SENSOR_ID)
- executor.runAllReady()
- verify(displayManager).unregisterDisplayListener(any())
- }
-
- @Test
- fun testShowOverlayReasonWhenDisplayChanged() = testWithDisplay {
- sideFpsController.show(SideFpsUiRequestSource.AUTO_SHOW, REASON_AUTH_KEYGUARD)
- executor.runAllReady()
- sideFpsController.orientationListener.onDisplayChanged(1 /* displayId */)
- executor.runAllReady()
-
- assertThat(sideFpsController.orientationReasonListener.reason)
- .isEqualTo(REASON_AUTH_KEYGUARD)
- }
-
- @Test
- fun testShowsAndHides() = testWithDisplay {
- overlayController.show(SENSOR_ID, REASON_UNKNOWN)
- executor.runAllReady()
-
- verify(windowManager).addView(overlayCaptor.capture(), any())
-
- reset(windowManager)
- overlayController.hide(SENSOR_ID)
- executor.runAllReady()
-
- verify(windowManager, never()).addView(any(), any())
- verify(windowManager).removeView(eq(overlayCaptor.value))
- }
-
- @Test
- fun testShowsOnce() = testWithDisplay {
- repeat(5) {
- overlayController.show(SENSOR_ID, REASON_UNKNOWN)
- executor.runAllReady()
- }
-
- verify(windowManager).addView(any(), any())
- verify(windowManager, never()).removeView(any())
- }
-
- @Test
- fun testHidesOnce() = testWithDisplay {
- overlayController.show(SENSOR_ID, REASON_UNKNOWN)
- executor.runAllReady()
-
- repeat(5) {
- overlayController.hide(SENSOR_ID)
- executor.runAllReady()
- }
-
- verify(windowManager).addView(any(), any())
- verify(windowManager).removeView(any())
- }
-
- @Test fun testIgnoredForKeyguard() = testWithDisplay { testIgnoredFor(REASON_AUTH_KEYGUARD) }
-
- @Test
- fun testShowsForMostSettings() = testWithDisplay {
- whenEver(activityTaskManager.getTasks(anyInt())).thenReturn(listOf(fpEnrollTask()))
- testIgnoredFor(REASON_AUTH_SETTINGS, ignored = false)
- }
-
- @Test
- fun testIgnoredForVerySpecificSettings() = testWithDisplay {
- whenEver(activityTaskManager.getTasks(anyInt())).thenReturn(listOf(fpSettingsTask()))
- testIgnoredFor(REASON_AUTH_SETTINGS)
- }
-
- private fun testIgnoredFor(reason: Int, ignored: Boolean = true) {
- overlayController.show(SENSOR_ID, reason)
- executor.runAllReady()
-
- verify(windowManager, if (ignored) never() else times(1)).addView(any(), any())
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_0() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_0 }
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_90() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_90 }
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_180() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_180 }
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_180() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_180 },
- windowInsets = insetsForSmallNavbar()
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_180() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_180 },
- windowInsets = insetsForLargeNavbar()
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_270() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_270 }
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_0() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- isReverseDefaultRotation = true,
- { rotation = Surface.ROTATION_0 }
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- isReverseDefaultRotation = true,
- { rotation = Surface.ROTATION_90 }
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarCollapsedDownForXAlignedSensor_InReverseDefaultRotation_90() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- isReverseDefaultRotation = true,
- { rotation = Surface.ROTATION_90 },
- windowInsets = insetsForSmallNavbar()
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun hidesSfpsIndicatorWhenOccludingTaskbarForXAlignedSensor_InReverseDefaultRotation_90() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- isReverseDefaultRotation = true,
- { rotation = Surface.ROTATION_90 },
- windowInsets = insetsForLargeNavbar()
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_180() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- isReverseDefaultRotation = true,
- { rotation = Surface.ROTATION_180 }
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForXAlignedSensor_InReverseDefaultRotation_270() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- isReverseDefaultRotation = true,
- { rotation = Surface.ROTATION_270 }
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_0() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_0 }
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_90() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_90 }
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_180() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_180 },
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_270() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_270 }
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_270() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_270 },
- windowInsets = insetsForSmallNavbar()
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_270() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_270 },
- windowInsets = insetsForLargeNavbar()
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_0() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = true,
- { rotation = Surface.ROTATION_0 }
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_90() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = true,
- { rotation = Surface.ROTATION_90 },
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_180() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = true,
- { rotation = Surface.ROTATION_180 }
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarCollapsedDownForYAlignedSensor_InReverseDefaultRotation_180() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = true,
- { rotation = Surface.ROTATION_180 },
- windowInsets = insetsForSmallNavbar()
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun hidesSfpsIndicatorWhenOccludingTaskbarForYAlignedSensor_InReverseDefaultRotation_180() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = true,
- { rotation = Surface.ROTATION_180 },
- windowInsets = insetsForLargeNavbar()
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = false)
- }
-
- @Test
- fun showsSfpsIndicatorWithTaskbarForYAlignedSensor_InReverseDefaultRotation_270() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = true,
- { rotation = Surface.ROTATION_270 }
- ) {
- verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible = true)
- }
-
- @Test
- fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_0() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_0 },
- inRearDisplayMode = true,
- ) {
- verifySfpsIndicator_notAdded_InRearDisplayMode()
- }
-
- @Test
- fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_90() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_90 },
- inRearDisplayMode = true,
- ) {
- verifySfpsIndicator_notAdded_InRearDisplayMode()
- }
-
- @Test
- fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_180() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_180 },
- inRearDisplayMode = true,
- ) {
- verifySfpsIndicator_notAdded_InRearDisplayMode()
- }
-
- @Test
- fun verifiesSfpsIndicatorNotAddedInRearDisplayMode_270() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_270 },
- inRearDisplayMode = true,
- ) {
- verifySfpsIndicator_notAdded_InRearDisplayMode()
- }
-
- private fun verifySfpsIndicatorVisibilityOnTaskbarUpdate(sfpsViewVisible: Boolean) {
- sideFpsController.overlayOffsets = sensorLocation
- }
-
- private fun verifySfpsIndicator_notAdded_InRearDisplayMode() {
- sideFpsController.overlayOffsets = sensorLocation
- overlayController.show(SENSOR_ID, REASON_UNKNOWN)
- executor.runAllReady()
-
- verify(windowManager, never()).addView(any(), any())
- }
-
- fun alternateBouncerVisibility_showAndHideSideFpsUI() = testWithDisplay {
- // WHEN alternate bouncer is visible
- keyguardBouncerRepository.setAlternateVisible(true)
- executor.runAllReady()
-
- // THEN side fps shows UI
- verify(windowManager).addView(any(), any())
- verify(windowManager, never()).removeView(any())
-
- // WHEN alternate bouncer is no longer visible
- keyguardBouncerRepository.setAlternateVisible(false)
- executor.runAllReady()
-
- // THEN side fps UI is hidden
- verify(windowManager).removeView(any())
- }
-
- /**
- * {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_0,
- * and uses RotateUtils.rotateBounds to map to the correct indicator location given the device
- * rotation. Assuming RotationUtils.rotateBounds works correctly, tests for indicator placement
- * in other rotations have been omitted.
- */
- @Test
- fun verifiesIndicatorPlacementForXAlignedSensor_0() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_0 }
- ) {
- sideFpsController.overlayOffsets = sensorLocation
-
- sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
-
- overlayController.show(SENSOR_ID, REASON_UNKNOWN)
- executor.runAllReady()
-
- verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
- assertThat(overlayViewParamsCaptor.value.x).isEqualTo(sensorLocation.sensorLocationX)
- assertThat(overlayViewParamsCaptor.value.y).isEqualTo(0)
- }
-
- /**
- * {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_270
- * in reverse default rotation. It then uses RotateUtils.rotateBounds to map to the correct
- * indicator location given the device rotation. Assuming RotationUtils.rotateBounds works
- * correctly, tests for indicator placement in other rotations have been omitted.
- */
- @Test
- fun verifiesIndicatorPlacementForXAlignedSensor_InReverseDefaultRotation_270() =
- testWithDisplay(
- deviceConfig = DeviceConfig.X_ALIGNED,
- isReverseDefaultRotation = true,
- { rotation = Surface.ROTATION_270 }
- ) {
- sideFpsController.overlayOffsets = sensorLocation
-
- sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
-
- overlayController.show(SENSOR_ID, REASON_UNKNOWN)
- executor.runAllReady()
-
- verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
- assertThat(overlayViewParamsCaptor.value.x).isEqualTo(sensorLocation.sensorLocationX)
- assertThat(overlayViewParamsCaptor.value.y).isEqualTo(0)
- }
-
- /**
- * {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_0,
- * and uses RotateUtils.rotateBounds to map to the correct indicator location given the device
- * rotation. Assuming RotationUtils.rotateBounds works correctly, tests for indicator placement
- * in other rotations have been omitted.
- */
- @Test
- fun verifiesIndicatorPlacementForYAlignedSensor_0() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = false,
- { rotation = Surface.ROTATION_0 }
- ) {
- sideFpsController.overlayOffsets = sensorLocation
-
- sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
-
- overlayController.show(SENSOR_ID, REASON_UNKNOWN)
- executor.runAllReady()
-
- verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
- assertThat(overlayViewParamsCaptor.value.x).isEqualTo(displayWidth - boundsWidth)
- assertThat(overlayViewParamsCaptor.value.y).isEqualTo(sensorLocation.sensorLocationY)
- }
-
- /**
- * {@link SideFpsController#updateOverlayParams} calculates indicator placement for ROTATION_270
- * in reverse default rotation. It then uses RotateUtils.rotateBounds to map to the correct
- * indicator location given the device rotation. Assuming RotationUtils.rotateBounds works
- * correctly, tests for indicator placement in other rotations have been omitted.
- */
- @Test
- fun verifiesIndicatorPlacementForYAlignedSensor_InReverseDefaultRotation_270() =
- testWithDisplay(
- deviceConfig = DeviceConfig.Y_ALIGNED,
- isReverseDefaultRotation = true,
- { rotation = Surface.ROTATION_270 }
- ) {
- sideFpsController.overlayOffsets = sensorLocation
-
- sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
-
- overlayController.show(SENSOR_ID, REASON_UNKNOWN)
- executor.runAllReady()
-
- verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
- assertThat(overlayViewParamsCaptor.value.x).isEqualTo(displayWidth - boundsWidth)
- assertThat(overlayViewParamsCaptor.value.y).isEqualTo(sensorLocation.sensorLocationY)
- }
-
- @Test
- fun hasSideFpsSensor_withSensorProps_returnsTrue() = testWithDisplay {
- // By default all those tests assume the side fps sensor is available.
- assertThat(fingerprintManager.hasSideFpsSensor()).isTrue()
- }
-
- @Test
- fun hasSideFpsSensor_withoutSensorProps_returnsFalse() {
- whenEver(fingerprintManager.sensorPropertiesInternal).thenReturn(null)
-
- assertThat(fingerprintManager.hasSideFpsSensor()).isFalse()
- }
-
- @Test
- fun testLayoutParams_isKeyguardDialogType() =
- testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED) {
- sideFpsController.overlayOffsets = sensorLocation
- sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
- overlayController.show(SENSOR_ID, REASON_UNKNOWN)
- executor.runAllReady()
-
- verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
-
- val lpType = overlayViewParamsCaptor.value.type
-
- assertThat((lpType and TYPE_KEYGUARD_DIALOG) != 0).isTrue()
- }
-
- @Test
- fun testLayoutParams_hasNoMoveAnimationWindowFlag() =
- testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED) {
- sideFpsController.overlayOffsets = sensorLocation
- sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
- overlayController.show(SENSOR_ID, REASON_UNKNOWN)
- executor.runAllReady()
-
- verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
-
- val lpFlags = overlayViewParamsCaptor.value.privateFlags
-
- assertThat((lpFlags and PRIVATE_FLAG_NO_MOVE_ANIMATION) != 0).isTrue()
- }
-
- @Test
- fun testLayoutParams_hasTrustedOverlayWindowFlag() =
- testWithDisplay(deviceConfig = DeviceConfig.Y_ALIGNED) {
- sideFpsController.overlayOffsets = sensorLocation
- sideFpsController.updateOverlayParams(windowManager.defaultDisplay, indicatorBounds)
- overlayController.show(SENSOR_ID, REASON_UNKNOWN)
- executor.runAllReady()
-
- verify(windowManager).updateViewLayout(any(), overlayViewParamsCaptor.capture())
-
- val lpFlags = overlayViewParamsCaptor.value.privateFlags
-
- assertThat((lpFlags and PRIVATE_FLAG_TRUSTED_OVERLAY) != 0).isTrue()
- }
-
- @Test
- fun primaryBouncerRequestAnimatesAlphaIn() = testWithDisplay {
- sideFpsController.show(SideFpsUiRequestSource.PRIMARY_BOUNCER, REASON_AUTH_KEYGUARD)
- executor.runAllReady()
- verify(sideFpsView).animate()
- }
-
- @Test
- fun alternateBouncerRequestsDoesNotAnimateAlphaIn() = testWithDisplay {
- sideFpsController.show(SideFpsUiRequestSource.ALTERNATE_BOUNCER, REASON_AUTH_KEYGUARD)
- executor.runAllReady()
- verify(sideFpsView, never()).animate()
- }
-
- @Test
- fun autoShowRequestsDoesNotAnimateAlphaIn() = testWithDisplay {
- sideFpsController.show(SideFpsUiRequestSource.AUTO_SHOW, REASON_AUTH_KEYGUARD)
- executor.runAllReady()
- verify(sideFpsView, never()).animate()
- }
-}
-
-private fun insetsForSmallNavbar() = insetsWithBottom(60)
-
-private fun insetsForLargeNavbar() = insetsWithBottom(100)
-
-private fun insetsWithBottom(bottom: Int) =
- WindowInsets.Builder()
- .setInsets(WindowInsets.Type.navigationBars(), Insets.of(0, 0, 0, bottom))
- .build()
-
-private fun fpEnrollTask() = settingsTask(".biometrics.fingerprint.FingerprintEnrollEnrolling")
-
-private fun fpSettingsTask() = settingsTask(".biometrics.fingerprint.FingerprintSettings")
-
-private fun settingsTask(cls: String) =
- ActivityManager.RunningTaskInfo().apply {
- topActivity = ComponentName.createRelative("com.android.settings", cls)
- }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt
index 63f6c20..546a6b7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractorTest.kt
@@ -36,8 +36,6 @@
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.FakeTrustRepository
import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.res.R
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.mockito.any
@@ -343,90 +341,6 @@
assertThat(underTest.willDismissWithAction()).isFalse()
}
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- @Test
- fun testSideFpsVisibility() {
- updateSideFpsVisibilityParameters(
- isVisible = true,
- sfpsEnabled = true,
- fpsDetectionRunning = true,
- isUnlockingWithFpAllowed = true,
- isAnimatingAway = false
- )
- underTest.updateSideFpsVisibility()
- verify(repository).setSideFpsShowing(true)
- }
-
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- @Test
- fun testSideFpsVisibility_notVisible() {
- updateSideFpsVisibilityParameters(
- isVisible = false,
- sfpsEnabled = true,
- fpsDetectionRunning = true,
- isUnlockingWithFpAllowed = true,
- isAnimatingAway = false
- )
- underTest.updateSideFpsVisibility()
- verify(repository).setSideFpsShowing(false)
- }
-
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- @Test
- fun testSideFpsVisibility_sfpsNotEnabled() {
- updateSideFpsVisibilityParameters(
- isVisible = true,
- sfpsEnabled = false,
- fpsDetectionRunning = true,
- isUnlockingWithFpAllowed = true,
- isAnimatingAway = false
- )
- underTest.updateSideFpsVisibility()
- verify(repository).setSideFpsShowing(false)
- }
-
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- @Test
- fun testSideFpsVisibility_fpsDetectionNotRunning() {
- updateSideFpsVisibilityParameters(
- isVisible = true,
- sfpsEnabled = true,
- fpsDetectionRunning = false,
- isUnlockingWithFpAllowed = true,
- isAnimatingAway = false
- )
- underTest.updateSideFpsVisibility()
- verify(repository).setSideFpsShowing(false)
- }
-
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- @Test
- fun testSideFpsVisibility_UnlockingWithFpNotAllowed() {
- updateSideFpsVisibilityParameters(
- isVisible = true,
- sfpsEnabled = true,
- fpsDetectionRunning = true,
- isUnlockingWithFpAllowed = false,
- isAnimatingAway = false
- )
- underTest.updateSideFpsVisibility()
- verify(repository).setSideFpsShowing(false)
- }
-
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- @Test
- fun testSideFpsVisibility_AnimatingAway() {
- updateSideFpsVisibilityParameters(
- isVisible = true,
- sfpsEnabled = true,
- fpsDetectionRunning = true,
- isUnlockingWithFpAllowed = true,
- isAnimatingAway = true
- )
- underTest.updateSideFpsVisibility()
- verify(repository).setSideFpsShowing(false)
- }
-
@Test
fun delayBouncerWhenFaceAuthPossible() {
mainHandler.setMode(FakeHandler.Mode.QUEUEING)
@@ -491,22 +405,4 @@
verify(repository).setPrimaryShowingSoon(false)
}
}
-
- private fun updateSideFpsVisibilityParameters(
- isVisible: Boolean,
- sfpsEnabled: Boolean,
- fpsDetectionRunning: Boolean,
- isUnlockingWithFpAllowed: Boolean,
- isAnimatingAway: Boolean
- ) {
- mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
- whenever(repository.primaryBouncerShow.value).thenReturn(isVisible)
- resources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer, sfpsEnabled)
- whenever(keyguardUpdateMonitor.isFingerprintDetectionRunning)
- .thenReturn(fpsDetectionRunning)
- whenever(keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
- .thenReturn(isUnlockingWithFpAllowed)
- whenever(repository.primaryBouncerStartingDisappearAnimation.value)
- .thenReturn(if (isAnimatingAway) Runnable {} else null)
- }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
index cddbd1f..1a43501 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModelTest.kt
@@ -33,7 +33,6 @@
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.TrustRepository
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.utils.os.FakeHandler
@@ -66,9 +65,7 @@
@Mock private lateinit var faceAuthInteractor: DeviceEntryFaceAuthInteractor
lateinit var bouncerInteractor: PrimaryBouncerInteractor
- private val mainHandler by lazy {
- FakeHandler(Looper.getMainLooper())
- }
+ private val mainHandler by lazy { FakeHandler(Looper.getMainLooper()) }
val repository = FakeKeyguardBouncerRepository()
lateinit var underTest: KeyguardBouncerViewModel
@@ -108,46 +105,6 @@
job.cancel()
}
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- @Test
- fun shouldUpdateSideFps_show() = runTest {
- mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
- var count = 0
- val job = underTest.shouldUpdateSideFps.onEach { count++ }.launchIn(this)
- repository.setPrimaryShow(true)
- // Run the tasks that are pending at this point of virtual time.
- runCurrent()
- assertThat(count).isEqualTo(1)
- job.cancel()
- }
-
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- @Test
- fun shouldUpdateSideFps_hide() = runTest {
- mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
- repository.setPrimaryShow(true)
- var count = 0
- val job = underTest.shouldUpdateSideFps.onEach { count++ }.launchIn(this)
- repository.setPrimaryShow(false)
- // Run the tasks that are pending at this point of virtual time.
- runCurrent()
- assertThat(count).isEqualTo(1)
- job.cancel()
- }
-
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- @Test
- fun sideFpsShowing() = runTest {
- mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
- var sideFpsIsShowing = false
- val job = underTest.sideFpsShowing.onEach { sideFpsIsShowing = it }.launchIn(this)
- repository.setSideFpsShowing(true)
- // Run the tasks that are pending at this point of virtual time.
- runCurrent()
- assertThat(sideFpsIsShowing).isEqualTo(true)
- job.cancel()
- }
-
@Test
fun isShowing() = runTest {
var isShowing: Boolean? = null
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalBackupRestoreStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalBackupRestoreStartableTest.kt
new file mode 100644
index 0000000..722eb2b
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalBackupRestoreStartableTest.kt
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2024 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.communal
+
+import android.appwidget.AppWidgetManager
+import android.content.Context
+import android.content.Intent
+import android.content.mockedContext
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.broadcast.FakeBroadcastDispatcher
+import com.android.systemui.broadcast.broadcastDispatcher
+import com.android.systemui.communal.domain.interactor.CommunalInteractor
+import com.android.systemui.communal.widgets.CommunalWidgetModule
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.log.logcatLogBuffer
+import com.android.systemui.testKosmos
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.kotlinArgumentCaptor
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CommunalBackupRestoreStartableTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+
+ @Mock private lateinit var communalInteractor: CommunalInteractor
+
+ private val mapCaptor = kotlinArgumentCaptor<Map<Int, Int>>()
+
+ private lateinit var context: Context
+ private lateinit var broadcastDispatcher: FakeBroadcastDispatcher
+ private lateinit var underTest: CommunalBackupRestoreStartable
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+
+ context = kosmos.mockedContext
+ broadcastDispatcher = kosmos.broadcastDispatcher
+
+ underTest =
+ CommunalBackupRestoreStartable(
+ broadcastDispatcher,
+ communalInteractor,
+ logcatLogBuffer("CommunalBackupRestoreStartable"),
+ )
+ }
+
+ @Test
+ fun testRestoreWidgetsUponHostRestored() =
+ testScope.runTest {
+ underTest.start()
+
+ // Verify restore widgets not called
+ verify(communalInteractor, never()).restoreWidgets(any())
+
+ // Trigger app widget host restored
+ val intent =
+ Intent().apply {
+ action = AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED
+ putExtra(
+ AppWidgetManager.EXTRA_HOST_ID,
+ CommunalWidgetModule.APP_WIDGET_HOST_ID
+ )
+ putExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS, intArrayOf(1, 2, 3))
+ putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, intArrayOf(7, 8, 9))
+ }
+ broadcastDispatcher.sendIntentToMatchingReceiversOnly(context, intent)
+
+ // Verify restore widgets called
+ verify(communalInteractor).restoreWidgets(mapCaptor.capture())
+ val oldToNewWidgetIdMap = mapCaptor.value
+ assertThat(oldToNewWidgetIdMap)
+ .containsExactlyEntriesIn(
+ mapOf(
+ Pair(1, 7),
+ Pair(2, 8),
+ Pair(3, 9),
+ )
+ )
+ }
+
+ @Test
+ fun testDoNotRestoreWidgetsIfNotForCommunalWidgetHost() =
+ testScope.runTest {
+ underTest.start()
+
+ // Trigger app widget host restored, but for another host
+ val hostId = CommunalWidgetModule.APP_WIDGET_HOST_ID + 1
+ val intent =
+ Intent().apply {
+ action = AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED
+ putExtra(AppWidgetManager.EXTRA_HOST_ID, hostId)
+ putExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS, intArrayOf(1, 2, 3))
+ putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, intArrayOf(7, 8, 9))
+ }
+ broadcastDispatcher.sendIntentToMatchingReceiversOnly(context, intent)
+
+ // Verify restore widgets not called
+ verify(communalInteractor, never()).restoreWidgets(any())
+ }
+
+ @Test
+ fun testAbortRestoreWidgetsIfOldToNewIdsMappingInvalid() =
+ testScope.runTest {
+ underTest.start()
+
+ // Trigger app widget host restored, but new ids list is one too many for old ids
+ val oldIds = intArrayOf(1, 2, 3)
+ val newIds = intArrayOf(6, 7, 8, 9)
+ val intent =
+ Intent().apply {
+ action = AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED
+ putExtra(
+ AppWidgetManager.EXTRA_HOST_ID,
+ CommunalWidgetModule.APP_WIDGET_HOST_ID
+ )
+ putExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS, oldIds)
+ putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, newIds)
+ }
+ broadcastDispatcher.sendIntentToMatchingReceiversOnly(context, intent)
+
+ // Verify restore widgets aborted
+ verify(communalInteractor).abortRestoreWidgets()
+ verify(communalInteractor, never()).restoreWidgets(any())
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt
index 76f15d2..b4b812d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt
@@ -32,7 +32,9 @@
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
+import com.android.systemui.statusbar.notificationShadeWindowController
import com.android.systemui.testKosmos
import com.android.systemui.util.settings.fakeSettings
import com.google.common.truth.Truth.assertThat
@@ -68,8 +70,10 @@
keyguardTransitionInteractor = keyguardTransitionInteractor,
keyguardInteractor = keyguardInteractor,
systemSettings = fakeSettings,
+ notificationShadeWindowController = notificationShadeWindowController,
applicationScope = applicationCoroutineScope,
bgScope = applicationCoroutineScope,
+ mainDispatcher = testDispatcher,
)
.apply { start() }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt
index a4c7abd..fe4d32d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/data/repository/CommunalWidgetRepositoryImplTest.kt
@@ -16,18 +16,23 @@
package com.android.systemui.communal.data.repository
+import android.app.backup.BackupManager
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProviderInfo
import android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_CONFIGURATION_OPTIONAL
import android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_RECONFIGURABLE
import android.content.ComponentName
+import android.content.applicationContext
import android.os.UserHandle
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.data.backup.CommunalBackupUtils
import com.android.systemui.communal.data.db.CommunalItemRank
import com.android.systemui.communal.data.db.CommunalWidgetDao
import com.android.systemui.communal.data.db.CommunalWidgetItem
+import com.android.systemui.communal.nano.CommunalHubState
+import com.android.systemui.communal.proto.toByteArray
import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
import com.android.systemui.communal.widgets.CommunalAppWidgetHost
import com.android.systemui.communal.widgets.CommunalWidgetHost
@@ -42,6 +47,7 @@
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
+import com.android.systemui.util.mockito.withArgCaptor
import com.google.common.truth.Truth.assertThat
import java.util.Optional
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -68,7 +74,9 @@
@Mock private lateinit var providerInfoA: AppWidgetProviderInfo
@Mock private lateinit var communalWidgetHost: CommunalWidgetHost
@Mock private lateinit var communalWidgetDao: CommunalWidgetDao
+ @Mock private lateinit var backupManager: BackupManager
+ private lateinit var backupUtils: CommunalBackupUtils
private lateinit var logBuffer: LogBuffer
private lateinit var fakeWidgets: MutableStateFlow<Map<CommunalItemRank, CommunalWidgetItem>>
@@ -89,6 +97,7 @@
MockitoAnnotations.initMocks(this)
fakeWidgets = MutableStateFlow(emptyMap())
logBuffer = logcatLogBuffer(name = "CommunalWidgetRepoImplTest")
+ backupUtils = CommunalBackupUtils(kosmos.applicationContext)
setAppWidgetIds(emptyList())
@@ -106,6 +115,8 @@
communalWidgetHost,
communalWidgetDao,
logBuffer,
+ backupManager,
+ backupUtils,
)
}
@@ -129,6 +140,9 @@
priority = communalItemRankEntry.rank,
)
)
+
+ // Verify backup not requested
+ verify(backupManager, never()).dataChanged()
}
@Test
@@ -152,6 +166,9 @@
verify(communalWidgetHost).allocateIdAndBindWidget(provider, user)
verify(communalWidgetDao).addWidget(id, provider, priority)
+
+ // Verify backup requested
+ verify(backupManager).dataChanged()
}
@Test
@@ -176,6 +193,9 @@
verify(communalWidgetHost).allocateIdAndBindWidget(provider, user)
verify(communalWidgetDao, never()).addWidget(id, provider, priority)
verify(appWidgetHost).deleteAppWidgetId(id)
+
+ // Verify backup not requested
+ verify(backupManager, never()).dataChanged()
}
@Test
@@ -202,6 +222,9 @@
verify(communalWidgetHost).allocateIdAndBindWidget(provider, user)
verify(communalWidgetDao, never()).addWidget(id, provider, priority)
verify(appWidgetHost).deleteAppWidgetId(id)
+
+ // Verify backup not requested
+ verify(backupManager, never()).dataChanged()
}
@Test
@@ -225,10 +248,13 @@
verify(communalWidgetHost).allocateIdAndBindWidget(provider, user)
verify(communalWidgetDao).addWidget(id, provider, priority)
+
+ // Verify backup requested
+ verify(backupManager).dataChanged()
}
@Test
- fun deleteWidget_deletefromDbTrue_alsoDeleteFromHost() =
+ fun deleteWidget_deleteFromDbTrue_alsoDeleteFromHost() =
testScope.runTest {
val id = 1
whenever(communalWidgetDao.deleteWidgetById(eq(id))).thenReturn(true)
@@ -237,10 +263,13 @@
verify(communalWidgetDao).deleteWidgetById(id)
verify(appWidgetHost).deleteAppWidgetId(id)
+
+ // Verify backup requested
+ verify(backupManager).dataChanged()
}
@Test
- fun deleteWidget_deletefromDbFalse_doesNotDeleteFromHost() =
+ fun deleteWidget_deleteFromDbFalse_doesNotDeleteFromHost() =
testScope.runTest {
val id = 1
whenever(communalWidgetDao.deleteWidgetById(eq(id))).thenReturn(false)
@@ -249,6 +278,9 @@
verify(communalWidgetDao).deleteWidgetById(id)
verify(appWidgetHost, never()).deleteAppWidgetId(id)
+
+ // Verify backup not requested
+ verify(backupManager, never()).dataChanged()
}
@Test
@@ -259,6 +291,147 @@
runCurrent()
verify(communalWidgetDao).updateWidgetOrder(widgetIdToPriorityMap)
+
+ // Verify backup requested
+ verify(backupManager).dataChanged()
+ }
+
+ @Test
+ fun restoreWidgets_deleteStateFileIfRestoreFails() =
+ testScope.runTest {
+ // Write a state file that is invalid, and verify it is written
+ backupUtils.writeBytesToDisk(byteArrayOf(1, 2, 3, 4, 5, 6))
+ assertThat(backupUtils.fileExists()).isTrue()
+
+ // Try to restore widgets
+ underTest.restoreWidgets(emptyMap())
+ runCurrent()
+
+ // The restore should fail, and verify that the file is deleted
+ assertThat(backupUtils.fileExists()).isFalse()
+ }
+
+ @Test
+ fun restoreWidgets_deleteStateFileAfterWidgetsRestored() =
+ testScope.runTest {
+ // Write a state file, and verify it is written
+ backupUtils.writeBytesToDisk(fakeState.toByteArray())
+ assertThat(backupUtils.fileExists()).isTrue()
+
+ // Set up app widget host with widget ids
+ setAppWidgetIds(listOf(11, 12))
+
+ // Restore widgets
+ underTest.restoreWidgets(mapOf(Pair(1, 11), Pair(2, 12)))
+ runCurrent()
+
+ // Verify state restored
+ verify(communalWidgetDao).restoreCommunalHubState(any())
+
+ // Verify state file deleted
+ assertThat(backupUtils.fileExists()).isFalse()
+ }
+
+ @Test
+ fun restoreWidgets_restoredWidgetsNotRegisteredWithHostAreSkipped() =
+ testScope.runTest {
+ // Write fake state to file
+ backupUtils.writeBytesToDisk(fakeState.toByteArray())
+
+ // Set up app widget host with widget ids. Widget 12 (previously 2) is absent.
+ setAppWidgetIds(listOf(11))
+
+ // Restore widgets.
+ underTest.restoreWidgets(mapOf(Pair(1, 11), Pair(2, 12)))
+ runCurrent()
+
+ // Verify state restored, and widget 2 skipped
+ val restoredState =
+ withArgCaptor<CommunalHubState> {
+ verify(communalWidgetDao).restoreCommunalHubState(capture())
+ }
+ val restoredWidgets = restoredState.widgets.toList()
+ assertThat(restoredWidgets).hasSize(1)
+
+ val restoredWidget = restoredWidgets.first()
+ val expectedWidget = fakeState.widgets.first()
+
+ // Verify widget id is updated, and the rest remain the same as expected
+ assertThat(restoredWidget.widgetId).isEqualTo(11)
+ assertThat(restoredWidget.componentName).isEqualTo(expectedWidget.componentName)
+ assertThat(restoredWidget.rank).isEqualTo(expectedWidget.rank)
+ }
+
+ @Test
+ fun restoreWidgets_registeredWidgetsNotRestoredAreRemoved() =
+ testScope.runTest {
+ // Write fake state to file
+ backupUtils.writeBytesToDisk(fakeState.toByteArray())
+
+ // Set up app widget host with widget ids. Widget 13 will not be restored.
+ setAppWidgetIds(listOf(11, 12, 13))
+
+ // Restore widgets.
+ underTest.restoreWidgets(mapOf(Pair(1, 11), Pair(2, 12)))
+ runCurrent()
+
+ // Verify widget 1 and 2 are restored, and are now 11 and 12.
+ val restoredState =
+ withArgCaptor<CommunalHubState> {
+ verify(communalWidgetDao).restoreCommunalHubState(capture())
+ }
+ val restoredWidgets = restoredState.widgets.toList()
+ assertThat(restoredWidgets).hasSize(2)
+
+ val restoredWidget1 = restoredWidgets[0]
+ val expectedWidget1 = fakeState.widgets[0]
+ assertThat(restoredWidget1.widgetId).isEqualTo(11)
+ assertThat(restoredWidget1.componentName).isEqualTo(expectedWidget1.componentName)
+ assertThat(restoredWidget1.rank).isEqualTo(expectedWidget1.rank)
+
+ val restoredWidget2 = restoredWidgets[1]
+ val expectedWidget2 = fakeState.widgets[1]
+ assertThat(restoredWidget2.widgetId).isEqualTo(12)
+ assertThat(restoredWidget2.componentName).isEqualTo(expectedWidget2.componentName)
+ assertThat(restoredWidget2.rank).isEqualTo(expectedWidget2.rank)
+
+ // Verify widget 13 removed since it is not restored
+ verify(appWidgetHost).deleteAppWidgetId(13)
+ }
+
+ @Test
+ fun restoreWidgets_onlySomeWidgetsGotNewIds() =
+ testScope.runTest {
+ // Write fake state to file
+ backupUtils.writeBytesToDisk(fakeState.toByteArray())
+
+ // Set up app widget host with widget ids. Widget 2 gets a new id: 12, but widget 1 does
+ // not.
+ setAppWidgetIds(listOf(1, 12))
+
+ // Restore widgets.
+ underTest.restoreWidgets(mapOf(Pair(2, 12)))
+ runCurrent()
+
+ // Verify widget 1 and 2 are restored, and are now 1 and 12.
+ val restoredState =
+ withArgCaptor<CommunalHubState> {
+ verify(communalWidgetDao).restoreCommunalHubState(capture())
+ }
+ val restoredWidgets = restoredState.widgets.toList()
+ assertThat(restoredWidgets).hasSize(2)
+
+ val restoredWidget1 = restoredWidgets[0]
+ val expectedWidget1 = fakeState.widgets[0]
+ assertThat(restoredWidget1.widgetId).isEqualTo(1)
+ assertThat(restoredWidget1.componentName).isEqualTo(expectedWidget1.componentName)
+ assertThat(restoredWidget1.rank).isEqualTo(expectedWidget1.rank)
+
+ val restoredWidget2 = restoredWidgets[1]
+ val expectedWidget2 = fakeState.widgets[1]
+ assertThat(restoredWidget2.widgetId).isEqualTo(12)
+ assertThat(restoredWidget2.componentName).isEqualTo(expectedWidget2.componentName)
+ assertThat(restoredWidget2.rank).isEqualTo(expectedWidget2.rank)
}
private fun installedProviders(providers: List<AppWidgetProviderInfo>) {
@@ -278,5 +451,22 @@
widgetFeatures =
WIDGET_FEATURE_CONFIGURATION_OPTIONAL or WIDGET_FEATURE_RECONFIGURABLE
}
+ val fakeState =
+ CommunalHubState().apply {
+ widgets =
+ listOf(
+ CommunalHubState.CommunalWidgetItem().apply {
+ widgetId = 1
+ componentName = "pk_name/fake_widget_1"
+ rank = 1
+ },
+ CommunalHubState.CommunalWidgetItem().apply {
+ widgetId = 2
+ componentName = "pk_name/fake_widget_2"
+ rank = 2
+ },
+ )
+ .toTypedArray()
+ }
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
index 5be765d..779e79ed 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt
@@ -44,11 +44,13 @@
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.kosmos.testScope
import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager
import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.settings.fakeUserTracker
+import com.android.systemui.shade.data.repository.fakeShadeRepository
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository
import com.android.systemui.smartspace.data.repository.fakeSmartspaceRepository
@@ -59,6 +61,7 @@
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -266,6 +269,26 @@
assertThat(isPopupOnDismissCtaShowing).isEqualTo(false)
}
+ @Test
+ fun canChangeScene_shadeNotExpanded() =
+ testScope.runTest {
+ // On keyguard without any shade expansion.
+ kosmos.fakeKeyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
+ kosmos.fakeShadeRepository.setLockscreenShadeExpansion(0f)
+ runCurrent()
+ assertThat(underTest.canChangeScene()).isTrue()
+ }
+
+ @Test
+ fun canChangeScene_shadeExpanded() =
+ testScope.runTest {
+ // On keyguard with shade fully expanded.
+ kosmos.fakeKeyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
+ kosmos.fakeShadeRepository.setLockscreenShadeExpansion(1f)
+ runCurrent()
+ assertThat(underTest.canChangeScene()).isFalse()
+ }
+
private suspend fun setIsMainUser(isMainUser: Boolean) {
whenever(user.isMain).thenReturn(isMainUser)
userRepository.setUserInfos(listOf(user))
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
index 41bc1dc..e2e5169 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayContainerViewControllerTest.java
@@ -16,6 +16,8 @@
package com.android.systemui.dreams;
+import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyFloat;
@@ -28,6 +30,7 @@
import android.content.res.Resources;
import android.graphics.Region;
import android.os.Handler;
+import android.testing.TestableLooper.RunWithLooper;
import android.view.AttachedSurfaceControl;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
@@ -43,6 +46,7 @@
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
import com.android.systemui.complication.ComplicationHostViewController;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.statusbar.BlurUtils;
import org.junit.Before;
@@ -52,8 +56,11 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import kotlinx.coroutines.CoroutineDispatcher;
+
@SmallTest
@RunWith(AndroidJUnit4.class)
+@RunWithLooper(setAsMainLooper = true)
public class DreamOverlayContainerViewControllerTest extends SysuiTestCase {
private static final int MAX_BURN_IN_OFFSET = 20;
private static final long BURN_IN_PROTECTION_UPDATE_INTERVAL = 10;
@@ -87,6 +94,9 @@
Handler mHandler;
@Mock
+ CoroutineDispatcher mDispatcher;
+
+ @Mock
BlurUtils mBlurUtils;
@Mock
@@ -103,6 +113,8 @@
@Mock
DreamOverlayStateController mStateController;
+ @Mock
+ KeyguardTransitionInteractor mKeyguardTransitionInteractor;
DreamOverlayContainerViewController mController;
@@ -115,6 +127,7 @@
when(mDreamOverlayContainerView.getViewRootImpl()).thenReturn(mViewRoot);
when(mDreamOverlayContainerView.getRootSurfaceControl())
.thenReturn(mAttachedSurfaceControl);
+ when(mKeyguardTransitionInteractor.isFinishedInStateWhere(any())).thenReturn(emptyFlow());
mController = new DreamOverlayContainerViewController(
mDreamOverlayContainerView,
@@ -124,6 +137,7 @@
mLowLightTransitionCoordinator,
mBlurUtils,
mHandler,
+ mDispatcher,
mResources,
MAX_BURN_IN_OFFSET,
BURN_IN_PROTECTION_UPDATE_INTERVAL,
@@ -131,7 +145,8 @@
mPrimaryBouncerCallbackInteractor,
mAnimationsController,
mStateController,
- mBouncerlessScrimController);
+ mBouncerlessScrimController,
+ mKeyguardTransitionInteractor);
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
index b18a8ec..bdb0c9a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
@@ -17,35 +17,52 @@
import android.content.ComponentName
import android.content.Intent
-import android.os.RemoteException
import android.service.dreams.IDreamOverlay
import android.service.dreams.IDreamOverlayCallback
import android.service.dreams.IDreamOverlayClient
import android.service.dreams.IDreamOverlayClientCallback
+import android.testing.TestableLooper
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.view.WindowManagerImpl
import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.ObservableTransitionState
import com.android.internal.logging.UiEventLogger
import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.SysuiTestCase
import com.android.systemui.ambient.touch.TouchMonitor
import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent
+import com.android.systemui.ambient.touch.scrim.ScrimController
+import com.android.systemui.ambient.touch.scrim.ScrimManager
+import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
+import com.android.systemui.communal.data.repository.FakeCommunalRepository
+import com.android.systemui.communal.data.repository.fakeCommunalRepository
+import com.android.systemui.communal.domain.interactor.communalInteractor
+import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.complication.ComplicationHostViewController
import com.android.systemui.complication.ComplicationLayoutEngine
import com.android.systemui.complication.dagger.ComplicationComponent
import com.android.systemui.dreams.complication.HideComplicationTouchHandler
import com.android.systemui.dreams.dagger.DreamOverlayComponent
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
import com.android.systemui.touch.TouchInsetManager
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
-import com.google.common.truth.Truth
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.test.runCurrent
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -53,20 +70,24 @@
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito
+import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
-import org.mockito.invocation.InvocationOnMock
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
@RunWith(AndroidJUnit4::class)
class DreamOverlayServiceTest : SysuiTestCase() {
private val mFakeSystemClock = FakeSystemClock()
private val mMainExecutor = FakeExecutor(mFakeSystemClock)
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
@Mock lateinit var mLifecycleOwner: DreamOverlayLifecycleOwner
- @Mock lateinit var mLifecycleRegistry: LifecycleRegistry
+ private lateinit var lifecycleRegistry: FakeLifecycleRegistry
- lateinit var mWindowParams: WindowManager.LayoutParams
+ private lateinit var mWindowParams: WindowManager.LayoutParams
@Mock lateinit var mDreamOverlayCallback: IDreamOverlayCallback
@@ -114,18 +135,33 @@
@Mock lateinit var mUiEventLogger: UiEventLogger
+ @Mock lateinit var mScrimManager: ScrimManager
+
+ @Mock lateinit var mScrimController: ScrimController
+
+ @Mock lateinit var mSystemDialogsCloser: SystemDialogsCloser
+
@Mock lateinit var mDreamOverlayCallbackController: DreamOverlayCallbackController
+ private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
+ private lateinit var communalRepository: FakeCommunalRepository
+
@Captor var mViewCaptor: ArgumentCaptor<View>? = null
- var mService: DreamOverlayService? = null
+ private lateinit var mService: DreamOverlayService
+
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
+
+ lifecycleRegistry = FakeLifecycleRegistry(mLifecycleOwner)
+ bouncerRepository = kosmos.fakeKeyguardBouncerRepository
+ communalRepository = kosmos.fakeCommunalRepository
+
whenever(mDreamOverlayComponent.getDreamOverlayContainerViewController())
.thenReturn(mDreamOverlayContainerViewController)
whenever(mComplicationComponent.getComplicationHostViewController())
.thenReturn(mComplicationHostViewController)
- whenever(mLifecycleOwner.registry).thenReturn(mLifecycleRegistry)
+ whenever(mLifecycleOwner.registry).thenReturn(lifecycleRegistry)
whenever(mComplicationComponentFactory.create(any(), any(), any(), any()))
.thenReturn(mComplicationComponent)
whenever(mComplicationComponent.getVisibilityController())
@@ -141,6 +177,7 @@
whenever(mAmbientTouchComponent.getTouchMonitor()).thenReturn(mTouchMonitor)
whenever(mDreamOverlayContainerViewController.containerView)
.thenReturn(mDreamOverlayContainerView)
+ whenever(mScrimManager.getCurrentController()).thenReturn(mScrimController)
mWindowParams = WindowManager.LayoutParams()
mService =
DreamOverlayService(
@@ -154,24 +191,30 @@
mAmbientTouchComponentFactory,
mStateController,
mKeyguardUpdateMonitor,
+ mScrimManager,
+ kosmos.communalInteractor,
+ mSystemDialogsCloser,
mUiEventLogger,
mTouchInsetManager,
LOW_LIGHT_COMPONENT,
HOME_CONTROL_PANEL_DREAM_COMPONENT,
mDreamOverlayCallbackController,
+ kosmos.keyguardInteractor,
WINDOW_NAME
)
}
- @get:Throws(RemoteException::class)
- val client: IDreamOverlayClient
+ private val client: IDreamOverlayClient
get() {
- val proxy = mService!!.onBind(Intent())
+ mService.onCreate()
+ TestableLooper.get(this).processAllMessages()
+
+ val proxy = mService.onBind(Intent())
val overlay = IDreamOverlay.Stub.asInterface(proxy)
val callback = Mockito.mock(IDreamOverlayClientCallback::class.java)
overlay.getClient(callback)
val clientCaptor = ArgumentCaptor.forClass(IDreamOverlayClient::class.java)
- Mockito.verify(callback).onDreamOverlayClient(clientCaptor.capture())
+ verify(callback).onDreamOverlayClient(clientCaptor.capture())
return clientCaptor.value
}
@@ -187,9 +230,8 @@
false /*shouldShowComplication*/
)
mMainExecutor.runAllReady()
- Mockito.verify(mUiEventLogger)
- .log(DreamOverlayService.DreamOverlayEvent.DREAM_OVERLAY_ENTER_START)
- Mockito.verify(mUiEventLogger)
+ verify(mUiEventLogger).log(DreamOverlayService.DreamOverlayEvent.DREAM_OVERLAY_ENTER_START)
+ verify(mUiEventLogger)
.log(DreamOverlayService.DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START)
}
@@ -205,7 +247,7 @@
false /*shouldShowComplication*/
)
mMainExecutor.runAllReady()
- Mockito.verify(mWindowManager).addView(any(), any())
+ verify(mWindowManager).addView(any(), any())
}
// Validates that {@link DreamOverlayService} properly handles the case where the dream's
@@ -224,14 +266,14 @@
false /*shouldShowComplication*/
)
mMainExecutor.runAllReady()
- Mockito.verify(mWindowManager).addView(any(), any())
- Mockito.verify(mStateController).setOverlayActive(false)
- Mockito.verify(mStateController).setLowLightActive(false)
- Mockito.verify(mStateController).setEntryAnimationsFinished(false)
- Mockito.verify(mStateController, Mockito.never()).setOverlayActive(true)
- Mockito.verify(mUiEventLogger, Mockito.never())
+ verify(mWindowManager).addView(any(), any())
+ verify(mStateController).setOverlayActive(false)
+ verify(mStateController).setLowLightActive(false)
+ verify(mStateController).setEntryAnimationsFinished(false)
+ verify(mStateController, Mockito.never()).setOverlayActive(true)
+ verify(mUiEventLogger, Mockito.never())
.log(DreamOverlayService.DreamOverlayEvent.DREAM_OVERLAY_COMPLETE_START)
- Mockito.verify(mDreamOverlayCallbackController, Mockito.never()).onStartDream()
+ verify(mDreamOverlayCallbackController, Mockito.never()).onStartDream()
}
@Test
@@ -246,7 +288,7 @@
false /*shouldShowComplication*/
)
mMainExecutor.runAllReady()
- Mockito.verify(mDreamOverlayContainerViewController).init()
+ verify(mDreamOverlayContainerViewController).init()
}
@Test
@@ -264,7 +306,7 @@
false /*shouldShowComplication*/
)
mMainExecutor.runAllReady()
- Mockito.verify(mDreamOverlayContainerViewParent).removeView(mDreamOverlayContainerView)
+ verify(mDreamOverlayContainerViewParent).removeView(mDreamOverlayContainerView)
}
@Test
@@ -279,7 +321,7 @@
true /*shouldShowComplication*/
)
mMainExecutor.runAllReady()
- Truth.assertThat(mService!!.shouldShowComplications()).isTrue()
+ assertThat(mService.shouldShowComplications()).isTrue()
}
@Test
@@ -294,8 +336,8 @@
false /*shouldShowComplication*/
)
mMainExecutor.runAllReady()
- Truth.assertThat(mService!!.dreamComponent).isEqualTo(LOW_LIGHT_COMPONENT)
- Mockito.verify(mStateController).setLowLightActive(true)
+ assertThat(mService.dreamComponent).isEqualTo(LOW_LIGHT_COMPONENT)
+ verify(mStateController).setLowLightActive(true)
}
@Test
@@ -310,8 +352,8 @@
false /*shouldShowComplication*/
)
mMainExecutor.runAllReady()
- Truth.assertThat(mService!!.dreamComponent).isEqualTo(HOME_CONTROL_PANEL_DREAM_COMPONENT)
- Mockito.verify(mStateController).setHomeControlPanelActive(true)
+ assertThat(mService.dreamComponent).isEqualTo(HOME_CONTROL_PANEL_DREAM_COMPONENT)
+ verify(mStateController).setHomeControlPanelActive(true)
}
@Test
@@ -328,19 +370,19 @@
mMainExecutor.runAllReady()
// Verify view added.
- Mockito.verify(mWindowManager).addView(mViewCaptor!!.capture(), any())
+ verify(mWindowManager).addView(mViewCaptor!!.capture(), any())
// Service destroyed.
- mService!!.onEndDream()
+ mService.onEndDream()
mMainExecutor.runAllReady()
// Verify view removed.
- Mockito.verify(mWindowManager).removeView(mViewCaptor!!.value)
+ verify(mWindowManager).removeView(mViewCaptor!!.value)
// Verify state correctly set.
- Mockito.verify(mStateController).setOverlayActive(false)
- Mockito.verify(mStateController).setLowLightActive(false)
- Mockito.verify(mStateController).setEntryAnimationsFinished(false)
+ verify(mStateController).setOverlayActive(false)
+ verify(mStateController).setLowLightActive(false)
+ verify(mStateController).setEntryAnimationsFinished(false)
}
@Test
@@ -373,7 +415,7 @@
// Schedule the endDream call in the middle of the startDream implementation, as any
// ordering is possible.
- Mockito.doAnswer { invocation: InvocationOnMock? ->
+ Mockito.doAnswer {
client.endDream()
null
}
@@ -409,37 +451,37 @@
mMainExecutor.runAllReady()
// Verify view added.
- Mockito.verify(mWindowManager).addView(mViewCaptor!!.capture(), any())
+ verify(mWindowManager).addView(mViewCaptor!!.capture(), any())
// Service destroyed.
- mService!!.onDestroy()
+ mService.onDestroy()
mMainExecutor.runAllReady()
// Verify view removed.
- Mockito.verify(mWindowManager).removeView(mViewCaptor!!.value)
+ verify(mWindowManager).removeView(mViewCaptor!!.value)
// Verify state correctly set.
- Mockito.verify(mKeyguardUpdateMonitor).removeCallback(any())
- Mockito.verify(mLifecycleRegistry).currentState = Lifecycle.State.DESTROYED
- Mockito.verify(mStateController).setOverlayActive(false)
- Mockito.verify(mStateController).setLowLightActive(false)
- Mockito.verify(mStateController).setEntryAnimationsFinished(false)
+ verify(mKeyguardUpdateMonitor).removeCallback(any())
+ assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.DESTROYED)
+ verify(mStateController).setOverlayActive(false)
+ verify(mStateController).setLowLightActive(false)
+ verify(mStateController).setEntryAnimationsFinished(false)
}
@Test
fun testDoNotRemoveViewOnDestroyIfOverlayNotStarted() {
// Service destroyed without ever starting dream.
- mService!!.onDestroy()
+ mService.onDestroy()
mMainExecutor.runAllReady()
// Verify no view is removed.
- Mockito.verify(mWindowManager, Mockito.never()).removeView(any())
+ verify(mWindowManager, Mockito.never()).removeView(any())
// Verify state still correctly set.
- Mockito.verify(mKeyguardUpdateMonitor).removeCallback(any())
- Mockito.verify(mLifecycleRegistry).currentState = Lifecycle.State.DESTROYED
- Mockito.verify(mStateController).setOverlayActive(false)
- Mockito.verify(mStateController).setLowLightActive(false)
+ verify(mKeyguardUpdateMonitor).removeCallback(any())
+ assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.DESTROYED)
+ verify(mStateController).setOverlayActive(false)
+ verify(mStateController).setLowLightActive(false)
}
@Test
@@ -447,7 +489,7 @@
val client = client
// Destroy the service.
- mService!!.onDestroy()
+ mService.onDestroy()
mMainExecutor.runAllReady()
// Inform the overlay service of dream starting.
@@ -458,15 +500,15 @@
false /*shouldShowComplication*/
)
mMainExecutor.runAllReady()
- Mockito.verify(mWindowManager, Mockito.never()).addView(any(), any())
+ verify(mWindowManager, Mockito.never()).addView(any(), any())
}
@Test
fun testNeverRemoveDecorViewIfNotAdded() {
// Service destroyed before dream started.
- mService!!.onDestroy()
+ mService.onDestroy()
mMainExecutor.runAllReady()
- Mockito.verify(mWindowManager, Mockito.never()).removeView(any())
+ verify(mWindowManager, Mockito.never()).removeView(any())
}
@Test
@@ -483,11 +525,11 @@
mMainExecutor.runAllReady()
// Verify that a new window is added.
- Mockito.verify(mWindowManager).addView(mViewCaptor!!.capture(), any())
+ verify(mWindowManager).addView(mViewCaptor!!.capture(), any())
val windowDecorView = mViewCaptor!!.value
// Assert that the overlay is not showing complications.
- Truth.assertThat(mService!!.shouldShowComplications()).isFalse()
+ assertThat(mService.shouldShowComplications()).isFalse()
Mockito.clearInvocations(mDreamOverlayComponent)
Mockito.clearInvocations(mAmbientTouchComponent)
Mockito.clearInvocations(mWindowManager)
@@ -504,16 +546,16 @@
mMainExecutor.runAllReady()
// Assert that the overlay is showing complications.
- Truth.assertThat(mService!!.shouldShowComplications()).isTrue()
+ assertThat(mService.shouldShowComplications()).isTrue()
// Verify that the old overlay window has been removed, and a new one created.
- Mockito.verify(mWindowManager).removeView(windowDecorView)
- Mockito.verify(mWindowManager).addView(any(), any())
+ verify(mWindowManager).removeView(windowDecorView)
+ verify(mWindowManager).addView(any(), any())
// Verify that new instances of overlay container view controller and overlay touch monitor
// are created.
- Mockito.verify(mDreamOverlayComponent).getDreamOverlayContainerViewController()
- Mockito.verify(mAmbientTouchComponent).getTouchMonitor()
+ verify(mDreamOverlayComponent).getDreamOverlayContainerViewController()
+ verify(mAmbientTouchComponent).getTouchMonitor()
}
@Test
@@ -528,15 +570,15 @@
true /*shouldShowComplication*/
)
mMainExecutor.runAllReady()
- mService!!.onWakeUp()
- Mockito.verify(mDreamOverlayContainerViewController).wakeUp()
- Mockito.verify(mDreamOverlayCallbackController).onWakeUp()
+ mService.onWakeUp()
+ verify(mDreamOverlayContainerViewController).wakeUp()
+ verify(mDreamOverlayCallbackController).onWakeUp()
}
@Test
fun testWakeUpBeforeStartDoesNothing() {
- mService!!.onWakeUp()
- Mockito.verify(mDreamOverlayContainerViewController, Mockito.never()).wakeUp()
+ mService.onWakeUp()
+ verify(mDreamOverlayContainerViewController, Mockito.never()).wakeUp()
}
@Test
@@ -554,8 +596,8 @@
val paramsCaptor = ArgumentCaptor.forClass(WindowManager.LayoutParams::class.java)
// Verify that a new window is added.
- Mockito.verify(mWindowManager).addView(any(), paramsCaptor.capture())
- Truth.assertThat(
+ verify(mWindowManager).addView(any(), paramsCaptor.capture())
+ assertThat(
paramsCaptor.value.privateFlags and
WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS ==
WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS
@@ -563,6 +605,254 @@
.isTrue()
}
+ // Tests that the bouncer closes when DreamOverlayService is told that the dream is coming to
+ // the front.
+ @Test
+ fun testBouncerRetractedWhenDreamComesToFront() {
+ val client = client
+
+ // Inform the overlay service of dream starting.
+ client.startDream(
+ mWindowParams,
+ mDreamOverlayCallback,
+ DREAM_COMPONENT,
+ true /*shouldShowComplication*/
+ )
+ mMainExecutor.runAllReady()
+
+ whenever(mDreamOverlayContainerViewController.isBouncerShowing()).thenReturn(true)
+ mService!!.onComeToFront()
+ verify(mScrimController).expand(any())
+ }
+
+ // Tests that glanceable hub is hidden when DreamOverlayService is told that the dream is
+ // coming to the front.
+ @Test
+ fun testGlanceableHubHiddenWhenDreamComesToFront() {
+ val client = client
+
+ // Inform the overlay service of dream starting.
+ client.startDream(
+ mWindowParams,
+ mDreamOverlayCallback,
+ DREAM_COMPONENT,
+ true /*shouldShowComplication*/
+ )
+ mMainExecutor.runAllReady()
+
+ mService!!.onComeToFront()
+ assertThat(communalRepository.currentScene.value).isEqualTo(CommunalScenes.Blank)
+ }
+
+ // Tests that system dialogs (e.g. notification shade) closes when DreamOverlayService is told
+ // that the dream is coming to the front.
+ @Test
+ fun testSystemDialogsClosedWhenDreamComesToFront() {
+ val client = client
+
+ // Inform the overlay service of dream starting.
+ client.startDream(
+ mWindowParams,
+ mDreamOverlayCallback,
+ DREAM_COMPONENT,
+ true /*shouldShowComplication*/
+ )
+ mMainExecutor.runAllReady()
+
+ mService!!.onComeToFront()
+ verify(mSystemDialogsCloser).closeSystemDialogs()
+ }
+
+ @Test
+ fun testLifecycle_createdAfterConstruction() {
+ mMainExecutor.runAllReady()
+ assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.CREATED)
+ }
+
+ @Test
+ fun testLifecycle_resumedAfterDreamStarts() {
+ val client = client
+
+ // Inform the overlay service of dream starting. Do not show dream complications.
+ client.startDream(
+ mWindowParams,
+ mDreamOverlayCallback,
+ DREAM_COMPONENT,
+ false /*shouldShowComplication*/
+ )
+ mMainExecutor.runAllReady()
+ assertThat(lifecycleRegistry.mLifecycles)
+ .containsExactly(
+ Lifecycle.State.CREATED,
+ Lifecycle.State.STARTED,
+ Lifecycle.State.RESUMED
+ )
+ }
+
+ @Test
+ fun testLifecycle_destroyedAfterOnDestroy() {
+ val client = client
+
+ // Inform the overlay service of dream starting. Do not show dream complications.
+ client.startDream(
+ mWindowParams,
+ mDreamOverlayCallback,
+ DREAM_COMPONENT,
+ false /*shouldShowComplication*/
+ )
+ mMainExecutor.runAllReady()
+ mService.onDestroy()
+ mMainExecutor.runAllReady()
+ assertThat(lifecycleRegistry.mLifecycles)
+ .containsExactly(
+ Lifecycle.State.CREATED,
+ Lifecycle.State.STARTED,
+ Lifecycle.State.RESUMED,
+ Lifecycle.State.DESTROYED
+ )
+ }
+
+ @Test
+ fun testNotificationShadeShown_setsLifecycleState() {
+ val client = client
+
+ // Inform the overlay service of dream starting. Do not show dream complications.
+ client.startDream(
+ mWindowParams,
+ mDreamOverlayCallback,
+ DREAM_COMPONENT,
+ false /*shouldShowComplication*/
+ )
+ mMainExecutor.runAllReady()
+ assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+ val callbackCaptor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
+ verify(mKeyguardUpdateMonitor).registerCallback(callbackCaptor.capture())
+
+ // Notification shade opens.
+ callbackCaptor.value.onShadeExpandedChanged(true)
+ mMainExecutor.runAllReady()
+
+ // Lifecycle state goes from resumed back to started when the notification shade shows.
+ assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.STARTED)
+
+ // Notification shade closes.
+ callbackCaptor.value.onShadeExpandedChanged(false)
+ mMainExecutor.runAllReady()
+
+ // Lifecycle state goes back to RESUMED.
+ assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+ }
+
+ @Test
+ fun testBouncerShown_setsLifecycleState() {
+ val client = client
+
+ // Inform the overlay service of dream starting. Do not show dream complications.
+ client.startDream(
+ mWindowParams,
+ mDreamOverlayCallback,
+ DREAM_COMPONENT,
+ false /*shouldShowComplication*/
+ )
+ mMainExecutor.runAllReady()
+ assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+
+ // Bouncer shows.
+ bouncerRepository.setPrimaryShow(true)
+ testScope.runCurrent()
+ mMainExecutor.runAllReady()
+
+ // Lifecycle state goes from resumed back to started when the notification shade shows.
+ assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.STARTED)
+
+ // Bouncer closes.
+ bouncerRepository.setPrimaryShow(false)
+ testScope.runCurrent()
+ mMainExecutor.runAllReady()
+
+ // Lifecycle state goes back to RESUMED.
+ assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+ }
+
+ @Test
+ fun testCommunalVisible_setsLifecycleState() {
+ val client = client
+
+ // Inform the overlay service of dream starting. Do not show dream complications.
+ client.startDream(
+ mWindowParams,
+ mDreamOverlayCallback,
+ DREAM_COMPONENT,
+ false /*shouldShowComplication*/
+ )
+ mMainExecutor.runAllReady()
+ assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+ val transitionState: MutableStateFlow<ObservableTransitionState> =
+ MutableStateFlow(ObservableTransitionState.Idle(CommunalScenes.Blank))
+ communalRepository.setTransitionState(transitionState)
+
+ // Communal becomes visible.
+ transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Communal)
+ testScope.runCurrent()
+ mMainExecutor.runAllReady()
+
+ // Lifecycle state goes from resumed back to started when the notification shade shows.
+ assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.STARTED)
+
+ // Communal closes.
+ transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Blank)
+ testScope.runCurrent()
+ mMainExecutor.runAllReady()
+
+ // Lifecycle state goes back to RESUMED.
+ assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+ }
+
+ // Verifies the dream's lifecycle
+ @Test
+ fun testLifecycleStarted_whenAnyOcclusion() {
+ val client = client
+
+ // Inform the overlay service of dream starting. Do not show dream complications.
+ client.startDream(
+ mWindowParams,
+ mDreamOverlayCallback,
+ DREAM_COMPONENT,
+ false /*shouldShowComplication*/
+ )
+ mMainExecutor.runAllReady()
+ assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+ val transitionState: MutableStateFlow<ObservableTransitionState> =
+ MutableStateFlow(ObservableTransitionState.Idle(CommunalScenes.Blank))
+ communalRepository.setTransitionState(transitionState)
+
+ // Communal becomes visible.
+ transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Communal)
+ testScope.runCurrent()
+ mMainExecutor.runAllReady()
+
+ // Lifecycle state goes from resumed back to started when the notification shade shows.
+ assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.STARTED)
+
+ // Communal closes.
+ transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Blank)
+ testScope.runCurrent()
+ mMainExecutor.runAllReady()
+
+ // Lifecycle state goes back to RESUMED.
+ assertThat(lifecycleRegistry.currentState).isEqualTo(Lifecycle.State.RESUMED)
+ }
+
+ internal class FakeLifecycleRegistry(provider: LifecycleOwner) : LifecycleRegistry(provider) {
+ val mLifecycles: MutableList<State> = ArrayList()
+
+ override var currentState: State
+ get() = mLifecycles[mLifecycles.size - 1]
+ set(state) {
+ mLifecycles.add(state)
+ }
+ }
+
companion object {
private val LOW_LIGHT_COMPONENT = ComponentName("package", "lowlight")
private val HOME_CONTROL_PANEL_DREAM_COMPONENT =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java
index 29fbee0..e3c6dee 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/touch/CommunalTouchHandlerTest.java
@@ -108,7 +108,7 @@
mTouchHandler.onSessionStart(mTouchSession);
verify(mTouchSession).registerInputListener(inputEventListenerArgumentCaptor.capture());
inputEventListenerArgumentCaptor.getValue().onInputEvent(motionEvent);
- verify(mCentralSurfaces).handleDreamTouch(motionEvent);
+ verify(mCentralSurfaces).handleExternalShadeWindowTouch(motionEvent);
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekableSliderHapticPluginTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekbarHapticPluginTest.kt
similarity index 96%
rename from packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekableSliderHapticPluginTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekbarHapticPluginTest.kt
index 805b4a8..855b6d0 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekableSliderHapticPluginTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekbarHapticPluginTest.kt
@@ -44,14 +44,14 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
@OptIn(ExperimentalCoroutinesApi::class)
-class SeekableSliderHapticPluginTest : SysuiTestCase() {
+class SeekbarHapticPluginTest : SysuiTestCase() {
private val kosmos = Kosmos()
@Rule @JvmField val mMockitoRule: MockitoRule = MockitoJUnit.rule()
@Mock private lateinit var vibratorHelper: VibratorHelper
private val seekBar = SeekBar(mContext)
- private lateinit var plugin: SeekableSliderHapticPlugin
+ private lateinit var plugin: SeekbarHapticPlugin
@Before
fun setup() {
@@ -142,7 +142,7 @@
private fun createPlugin() {
plugin =
- SeekableSliderHapticPlugin(
+ SeekbarHapticPlugin(
vibratorHelper,
kosmos.fakeSystemClock,
)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderStateProducerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderStateProducerTest.kt
new file mode 100644
index 0000000..88189db
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderStateProducerTest.kt
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2024 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.haptics.slider
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import junit.framework.Assert.assertEquals
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class SliderStateProducerTest : SysuiTestCase() {
+
+ private val eventProducer = SliderStateProducer()
+ private val eventFlow = eventProducer.produceEvents()
+
+ @Test
+ fun onStartTrackingTouch_noProgress_trackingTouchEventProduced() = runTest {
+ val latest by collectLastValue(eventFlow)
+
+ eventProducer.onStartTracking(/*fromUser =*/ true)
+
+ assertEquals(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, 0F), latest)
+ }
+
+ @Test
+ fun onStopTrackingTouch_noProgress_StoppedTrackingTouchEventProduced() = runTest {
+ val latest by collectLastValue(eventFlow)
+
+ eventProducer.onStopTracking(/*fromUser =*/ true)
+
+ assertEquals(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0F), latest)
+ }
+
+ @Test
+ fun onStartTrackingProgram_noProgress_trackingTouchEventProduced() = runTest {
+ val latest by collectLastValue(eventFlow)
+
+ eventProducer.onStartTracking(/*fromUser =*/ false)
+
+ assertEquals(SliderEvent(SliderEventType.STARTED_TRACKING_PROGRAM, 0F), latest)
+ }
+
+ @Test
+ fun onStopTrackingProgram_noProgress_StoppedTrackingTouchEventProduced() = runTest {
+ val latest by collectLastValue(eventFlow)
+
+ eventProducer.onStopTracking(/*fromUser =*/ false)
+
+ assertEquals(SliderEvent(SliderEventType.STOPPED_TRACKING_PROGRAM, 0F), latest)
+ }
+
+ @Test
+ fun onProgressChangeByUser_changeByUserEventProduced() = runTest {
+ val progress = 0.5f
+ val latest by collectLastValue(eventFlow)
+
+ eventProducer.onProgressChanged(/*fromUser =*/ true, progress)
+
+ assertEquals(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, progress), latest)
+ }
+
+ @Test
+ fun onProgressChangeByProgram_changeByProgramEventProduced() = runTest {
+ val progress = 0.5f
+ val latest by collectLastValue(eventFlow)
+
+ eventProducer.onProgressChanged(/*fromUser =*/ false, progress)
+
+ assertEquals(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress), latest)
+ }
+
+ @Test
+ fun onStartTrackingTouch_afterProgress_trackingTouchEventProduced() = runTest {
+ val progress = 0.5f
+ val latest by collectLastValue(eventFlow)
+
+ eventProducer.onProgressChanged(/*fromUser =*/ true, progress)
+ eventProducer.onStartTracking(/*fromUser =*/ true)
+
+ assertEquals(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress), latest)
+ }
+
+ @Test
+ fun onStopTrackingTouch_afterProgress_stopTrackingTouchEventProduced() = runTest {
+ val progress = 0.5f
+ val latest by collectLastValue(eventFlow)
+
+ eventProducer.onProgressChanged(/*fromUser =*/ true, progress)
+ eventProducer.onStopTracking(/*fromUser =*/ true)
+
+ assertEquals(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, progress), latest)
+ }
+
+ @Test
+ fun onStartTrackingProgram_afterProgress_trackingProgramEventProduced() = runTest {
+ val progress = 0.5f
+ val latest by collectLastValue(eventFlow)
+
+ eventProducer.onProgressChanged(/*fromUser =*/ false, progress)
+ eventProducer.onStartTracking(/*fromUser =*/ false)
+
+ assertEquals(SliderEvent(SliderEventType.STARTED_TRACKING_PROGRAM, progress), latest)
+ }
+
+ @Test
+ fun onStopTrackingProgram_afterProgress_stopTrackingProgramEventProduced() = runTest {
+ val progress = 0.5f
+ val latest by collectLastValue(eventFlow)
+
+ eventProducer.onProgressChanged(/*fromUser =*/ false, progress)
+ eventProducer.onStopTracking(/*fromUser =*/ false)
+
+ assertEquals(SliderEvent(SliderEventType.STOPPED_TRACKING_PROGRAM, progress), latest)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt
similarity index 97%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt
index 52bdf0e..cfc6b33 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt
@@ -46,11 +46,12 @@
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.power.shared.model.WakefulnessState
import com.android.systemui.testKosmos
-import kotlin.test.Test
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
+import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.mockito.Mockito.reset
@@ -124,6 +125,8 @@
)
kosmos.fakeKeyguardRepository.setKeyguardOccluded(true)
kosmos.fakeKeyguardBouncerRepository.setAlternateVisible(true)
+ runCurrent()
+
transitionRepository.sendTransitionSteps(
from = KeyguardState.OCCLUDED,
to = KeyguardState.ALTERNATE_BOUNCER,
@@ -132,8 +135,7 @@
reset(transitionRepository)
kosmos.fakeKeyguardBouncerRepository.setAlternateVisible(false)
- runCurrent()
- testScope.testScheduler.advanceTimeBy(200) // advance past delay
+ advanceTimeBy(200) // advance past delay
assertThat(transitionRepository)
.startedTransition(
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModelTest.kt
index f400cb1..0588b1c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/SideFpsProgressBarViewModelTest.kt
@@ -59,6 +59,7 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
@OptIn(ExperimentalCoroutinesApi::class)
@@ -69,6 +70,7 @@
private val kosmos = testKosmos()
private lateinit var underTest: SideFpsProgressBarViewModel
private val testScope = kosmos.testScope
+ private val dozeServiceHost = spy(kosmos.dozeServiceHost)
private lateinit var mTestableLooper: TestableLooper
@Before
@@ -175,7 +177,7 @@
runCurrent()
- verify(kosmos.dozeServiceHost).fireSideFpsAcquisitionStarted()
+ verify(dozeServiceHost).fireSideFpsAcquisitionStarted()
}
private fun createViewModel() =
@@ -184,7 +186,7 @@
kosmos.biometricStatusInteractor,
kosmos.deviceEntryFingerprintAuthInteractor,
kosmos.sideFpsSensorInteractor,
- kosmos.dozeServiceHost,
+ dozeServiceHost,
kosmos.keyguardInteractor,
kosmos.displayStateInteractor,
kosmos.testDispatcher,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index 6fa2273..2586ad541 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -25,10 +25,12 @@
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
+import com.android.internal.logging.uiEventLoggerFake
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.bouncer.domain.interactor.bouncerInteractor
+import com.android.systemui.bouncer.shared.logging.BouncerUiEvent
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.classifier.falsingCollector
import com.android.systemui.classifier.falsingManager
@@ -39,6 +41,7 @@
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeTrustRepository
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
import com.android.systemui.model.sysUiState
@@ -97,6 +100,8 @@
private val windowController = kosmos.notificationShadeWindowController
private val centralSurfaces = kosmos.centralSurfaces
private val powerInteractor = kosmos.powerInteractor
+ private val fakeTrustRepository = kosmos.fakeTrustRepository
+ private val uiEventLoggerFake = kosmos.uiEventLoggerFake
private lateinit var underTest: SceneContainerStartable
@@ -1233,6 +1238,25 @@
assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
}
+ @Test
+ fun switchToGone_extendUnlock() =
+ testScope.runTest {
+ val currentScene by collectLastValue(sceneInteractor.currentScene)
+ prepareState(
+ initialSceneKey = Scenes.Bouncer,
+ authenticationMethod = AuthenticationMethodModel.Pin,
+ )
+ assertThat(currentScene).isEqualTo(Scenes.Bouncer)
+
+ underTest.start()
+ fakeTrustRepository.setCurrentUserTrusted(true)
+
+ assertThat(currentScene).isEqualTo(Scenes.Gone)
+ assertThat(uiEventLoggerFake[0].eventId)
+ .isEqualTo(BouncerUiEvent.BOUNCER_DISMISS_EXTENDED_ACCESS.id)
+ assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
+ }
+
private fun TestScope.emulateSceneTransition(
transitionStateFlow: MutableStateFlow<ObservableTransitionState>,
toScene: SceneKey,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagParameterizationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagParameterizationTest.kt
index db31ad5..4d69f0d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagParameterizationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagParameterizationTest.kt
@@ -24,6 +24,7 @@
import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.andSceneContainer
+import com.android.systemui.flags.parameterizeSceneContainerFlag
import com.google.common.truth.Truth
import org.junit.Test
import org.junit.runner.RunWith
@@ -41,6 +42,14 @@
}
@Test
+ fun parameterizeSceneContainer() {
+ val result = parameterizeSceneContainerFlag()
+ Truth.assertThat(result).hasSize(2)
+ Truth.assertThat(result[0].mOverrides[FLAG_SCENE_CONTAINER]).isFalse()
+ Truth.assertThat(result[1].mOverrides[FLAG_SCENE_CONTAINER]).isTrue()
+ }
+
+ @Test
fun oneUnrelatedAndSceneContainer() {
val unrelatedFlag = FLAG_EXAMPLE_FLAG
val result = FlagsParameterization.allCombinationsOf(unrelatedFlag).andSceneContainer()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
similarity index 77%
rename from packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index b89ccef..a8da116 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -29,7 +29,6 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
@@ -37,12 +36,10 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
-import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
-
import android.app.IActivityManager;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
-import android.testing.AndroidTestingRunner;
+import android.platform.test.flag.junit.FlagsParameterization;
import android.testing.TestableLooper.RunWithLooper;
import android.view.View;
import android.view.WindowManager;
@@ -50,51 +47,26 @@
import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
-import com.android.keyguard.KeyguardSecurityModel;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
-import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository;
import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository;
-import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
import com.android.systemui.communal.domain.interactor.CommunalInteractor;
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FakeFeatureFlagsClassic;
+import com.android.systemui.flags.SceneContainerFlagParameterizationKt;
import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.keyguard.data.repository.FakeCommandQueue;
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository;
-import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor;
-import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.power.domain.interactor.PowerInteractor;
import com.android.systemui.res.R;
import com.android.systemui.scene.FakeWindowRootViewComponent;
-import com.android.systemui.scene.data.repository.SceneContainerRepository;
-import com.android.systemui.scene.domain.interactor.SceneInteractor;
-import com.android.systemui.scene.shared.logger.SceneLogger;
import com.android.systemui.settings.UserTracker;
-import com.android.systemui.shade.data.repository.FakeShadeRepository;
-import com.android.systemui.shade.domain.interactor.ShadeInteractor;
-import com.android.systemui.shade.domain.interactor.ShadeInteractorImpl;
-import com.android.systemui.shade.domain.interactor.ShadeInteractorLegacyImpl;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository;
-import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController;
-import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
-import com.android.systemui.user.domain.interactor.UserSwitcherInteractor;
import com.google.common.util.concurrent.MoreExecutors;
@@ -110,13 +82,13 @@
import java.util.List;
import java.util.concurrent.Executor;
-import kotlinx.coroutines.test.TestScope;
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
-@RunWith(AndroidTestingRunner.class)
+@RunWith(ParameterizedAndroidJunit4.class)
@RunWithLooper(setAsMainLooper = true)
@SmallTest
public class NotificationShadeWindowControllerImplTest extends SysuiTestCase {
-
@Mock private WindowManager mWindowManager;
@Mock private DozeParameters mDozeParameters;
@Spy private final NotificationShadeWindowView mNotificationShadeWindowView = spy(
@@ -128,29 +100,31 @@
@Mock private SysuiColorExtractor mColorExtractor;
@Mock private ColorExtractor.GradientColors mGradientColors;
@Mock private DumpManager mDumpManager;
- @Mock private KeyguardSecurityModel mKeyguardSecurityModel;
@Mock private KeyguardStateController mKeyguardStateController;
@Mock private AuthController mAuthController;
@Mock private ShadeWindowLogger mShadeWindowLogger;
@Mock private SelectedUserInteractor mSelectedUserInteractor;
@Mock private UserTracker mUserTracker;
- @Mock private LargeScreenHeaderHelper mLargeScreenHeaderHelper;
@Captor private ArgumentCaptor<WindowManager.LayoutParams> mLayoutParameters;
@Captor private ArgumentCaptor<StatusBarStateController.StateListener> mStateListener;
private final Executor mMainExecutor = MoreExecutors.directExecutor();
private final Executor mBackgroundExecutor = MoreExecutors.directExecutor();
private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this);
- private final TestScope mTestScope = mKosmos.getTestScope();
- private ShadeInteractor mShadeInteractor;
private NotificationShadeWindowControllerImpl mNotificationShadeWindowController;
private float mPreferredRefreshRate = -1;
- private FromLockscreenTransitionInteractor mFromLockscreenTransitionInteractor;
- private FromPrimaryBouncerTransitionInteractor mFromPrimaryBouncerTransitionInteractor;
- private ScreenOffAnimationController mScreenOffAnimationController;
private SysuiStatusBarStateController mStatusBarStateController;
+ @Parameters(name = "{0}")
+ public static List<FlagsParameterization> getParams() {
+ return SceneContainerFlagParameterizationKt.parameterizeSceneContainerFlag();
+ }
+
+ public NotificationShadeWindowControllerImplTest(FlagsParameterization flags) {
+ mSetFlagsRule.setFlagsParameterization(flags);
+ }
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -164,71 +138,7 @@
when(mDozeParameters.getAlwaysOn()).thenReturn(true);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
- FakeKeyguardRepository keyguardRepository = new FakeKeyguardRepository();
- FakeFeatureFlagsClassic featureFlags = new FakeFeatureFlagsClassic();
- FakeShadeRepository shadeRepository = new FakeShadeRepository();
-
- mScreenOffAnimationController = mKosmos.getScreenOffAnimationController();
mStatusBarStateController = spy(mKosmos.getStatusBarStateController());
- PowerInteractor powerInteractor = mKosmos.getPowerInteractor();
-
- SceneInteractor sceneInteractor = new SceneInteractor(
- mTestScope.getBackgroundScope(),
- new SceneContainerRepository(
- mTestScope.getBackgroundScope(),
- mKosmos.getFakeSceneContainerConfig(),
- mKosmos.getSceneDataSource()),
- mock(SceneLogger.class),
- mKosmos.getDeviceUnlockedInteractor());
-
- FakeConfigurationRepository configurationRepository = new FakeConfigurationRepository();
- KeyguardTransitionInteractor keyguardTransitionInteractor =
- mKosmos.getKeyguardTransitionInteractor();
- KeyguardInteractor keyguardInteractor = new KeyguardInteractor(
- keyguardRepository,
- new FakeCommandQueue(),
- powerInteractor,
- new FakeKeyguardBouncerRepository(),
- new ConfigurationInteractor(configurationRepository),
- shadeRepository,
- keyguardTransitionInteractor,
- () -> sceneInteractor,
- () -> mKosmos.getFromGoneTransitionInteractor(),
- () -> mKosmos.getSharedNotificationContainerInteractor(),
- mTestScope);
- CommunalInteractor communalInteractor = mKosmos.getCommunalInteractor();
-
- mFromLockscreenTransitionInteractor = mKosmos.getFromLockscreenTransitionInteractor();
- mFromPrimaryBouncerTransitionInteractor =
- mKosmos.getFromPrimaryBouncerTransitionInteractor();
-
- DeviceEntryUdfpsInteractor deviceEntryUdfpsInteractor =
- mock(DeviceEntryUdfpsInteractor.class);
- when(deviceEntryUdfpsInteractor.isUdfpsSupported()).thenReturn(MutableStateFlow(false));
-
- mShadeInteractor = new ShadeInteractorImpl(
- mTestScope.getBackgroundScope(),
- mKosmos.getDeviceProvisioningInteractor(),
- new FakeDisableFlagsRepository(),
- mock(DozeParameters.class),
- keyguardRepository,
- keyguardTransitionInteractor,
- powerInteractor,
- new FakeUserSetupRepository(),
- mock(UserSwitcherInteractor.class),
- new ShadeInteractorLegacyImpl(
- mTestScope.getBackgroundScope(),
- keyguardRepository,
- new SharedNotificationContainerInteractor(
- configurationRepository,
- mContext,
- new ResourcesSplitShadeStateController(),
- keyguardInteractor,
- deviceEntryUdfpsInteractor,
- () -> mLargeScreenHeaderHelper),
- shadeRepository
- )
- );
mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(
mContext,
@@ -245,13 +155,13 @@
mColorExtractor,
mDumpManager,
mKeyguardStateController,
- mScreenOffAnimationController,
+ mKosmos.getScreenOffAnimationController(),
mAuthController,
- () -> mShadeInteractor,
+ mKosmos::getShadeInteractor,
mShadeWindowLogger,
() -> mSelectedUserInteractor,
mUserTracker,
- () -> communalInteractor) {
+ mKosmos::getCommunalInteractor) {
@Override
protected boolean isDebuggable() {
return false;
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt
index 96b2b7a..aa0ca18 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt
@@ -24,7 +24,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.andSceneContainer
+import com.android.systemui.flags.parameterizeSceneContainerFlag
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.DozeStateModel
@@ -80,7 +80,7 @@
@JvmStatic
@Parameters(name = "{0}")
fun getParams(): List<FlagsParameterization> {
- return FlagsParameterization.allCombinationsOf().andSceneContainer()
+ return parameterizeSceneContainerFlag()
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt
index 2ab934c..07c4b00 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt
@@ -16,7 +16,7 @@
package com.android.systemui.shade.domain.startable
-import androidx.test.ext.junit.runners.AndroidJUnit4
+import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
@@ -25,9 +25,8 @@
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
-import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.flags.parameterizeSceneContainerFlag
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
@@ -50,24 +49,42 @@
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
-@RunWith(AndroidJUnit4::class)
-class ShadeStartableTest : SysuiTestCase() {
+@RunWith(ParameterizedAndroidJunit4::class)
+class ShadeStartableTest(flags: FlagsParameterization?) : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
- private val shadeInteractor = kosmos.shadeInteractor
- private val sceneInteractor = kosmos.sceneInteractor
- private val shadeExpansionStateManager = kosmos.shadeExpansionStateManager
- private val deviceEntryRepository = kosmos.fakeDeviceEntryRepository
- private val deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor
- private val fakeConfigurationRepository = kosmos.fakeConfigurationRepository
- private val fakeSceneDataSource = kosmos.fakeSceneDataSource
+ private val shadeInteractor by lazy { kosmos.shadeInteractor }
+ private val sceneInteractor by lazy { kosmos.sceneInteractor }
+ private val shadeExpansionStateManager by lazy { kosmos.shadeExpansionStateManager }
+ private val fakeConfigurationRepository by lazy { kosmos.fakeConfigurationRepository }
+ private val fakeSceneDataSource by lazy { kosmos.fakeSceneDataSource }
- private val underTest = kosmos.shadeStartable
+ private lateinit var underTest: ShadeStartable
+
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return parameterizeSceneContainerFlag()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
+
+ @Before
+ fun setup() {
+ underTest = kosmos.shadeStartable
+ }
@Test
fun hydrateShadeMode() =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
index 2397de6..5312ad8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
@@ -28,6 +28,7 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
@@ -65,6 +66,7 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
+@EnableSceneContainer
class ShadeSceneViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
similarity index 69%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
rename to packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
index be5af88..fc9535c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -19,60 +19,32 @@
package com.android.systemui.statusbar
import android.animation.ObjectAnimator
-import android.testing.AndroidTestingRunner
+import android.platform.test.flag.junit.FlagsParameterization
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
import com.android.internal.logging.testing.UiEventLoggerFake
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
-import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
-import com.android.systemui.classifier.FalsingCollectorFake
-import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
-import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.flags.EnableSceneContainer
-import com.android.systemui.flags.FakeFeatureFlagsClassic
+import com.android.systemui.flags.parameterizeSceneContainerFlag
import com.android.systemui.jank.interactionJankMonitor
-import com.android.systemui.keyguard.data.repository.FakeCommandQueue
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
-import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.fromGoneTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.fromLockscreenTransitionInteractor
-import com.android.systemui.keyguard.domain.interactor.fromPrimaryBouncerTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardClockInteractor
-import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.power.data.repository.FakePowerRepository
-import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.shade.LargeScreenHeaderHelper
-import com.android.systemui.shade.data.repository.FakeShadeRepository
-import com.android.systemui.shade.domain.interactor.ShadeInteractor
-import com.android.systemui.shade.domain.interactor.ShadeInteractorImpl
-import com.android.systemui.shade.domain.interactor.ShadeInteractorLegacyImpl
-import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository
-import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
-import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
-import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
-import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupRepository
-import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor
+import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.testKosmos
import com.android.systemui.util.kotlin.JavaAdapter
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
@@ -87,26 +59,34 @@
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
-import org.mockito.Mockito.`when` as whenever
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
@SmallTest
-@RunWith(AndroidTestingRunner::class)
+@RunWith(ParameterizedAndroidJunit4::class)
@TestableLooper.RunWithLooper
-class StatusBarStateControllerImplTest : SysuiTestCase() {
+class StatusBarStateControllerImplTest(flags: FlagsParameterization?) : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
- private lateinit var shadeInteractor: ShadeInteractor
- private lateinit var fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor
- private lateinit var fromPrimaryBouncerTransitionInteractor:
- FromPrimaryBouncerTransitionInteractor
+
private val mockDarkAnimator = mock<ObjectAnimator>()
- private val deviceEntryUdfpsInteractor = mock<DeviceEntryUdfpsInteractor>()
- private val largeScreenHeaderHelper = mock<LargeScreenHeaderHelper>()
private lateinit var underTest: StatusBarStateControllerImpl
private lateinit var uiEventLogger: UiEventLoggerFake
+ companion object {
+ @JvmStatic
+ @Parameters(name = "{0}")
+ fun getParams(): List<FlagsParameterization> {
+ return parameterizeSceneContainerFlag()
+ }
+ }
+
+ init {
+ mSetFlagsRule.setFlagsParameterization(flags!!)
+ }
+
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
@@ -118,7 +98,7 @@
uiEventLogger,
kosmos.interactionJankMonitor,
JavaAdapter(testScope.backgroundScope),
- { shadeInteractor },
+ { kosmos.shadeInteractor },
{ kosmos.deviceUnlockedInteractor },
{ kosmos.sceneInteractor },
{ kosmos.keyguardClockInteractor },
@@ -127,59 +107,6 @@
return mockDarkAnimator
}
}
-
- val powerInteractor =
- PowerInteractor(FakePowerRepository(), FalsingCollectorFake(), mock(), underTest)
- val keyguardRepository = FakeKeyguardRepository()
- val keyguardTransitionRepository = FakeKeyguardTransitionRepository()
- val featureFlags = FakeFeatureFlagsClassic()
- val shadeRepository = FakeShadeRepository()
- val configurationRepository = FakeConfigurationRepository()
- val keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor
- fromLockscreenTransitionInteractor = kosmos.fromLockscreenTransitionInteractor
- fromPrimaryBouncerTransitionInteractor = kosmos.fromPrimaryBouncerTransitionInteractor
-
- val keyguardInteractor =
- KeyguardInteractor(
- keyguardRepository,
- FakeCommandQueue(),
- powerInteractor,
- FakeKeyguardBouncerRepository(),
- ConfigurationInteractor(configurationRepository),
- shadeRepository,
- keyguardTransitionInteractor,
- { kosmos.sceneInteractor },
- { kosmos.fromGoneTransitionInteractor },
- { kosmos.sharedNotificationContainerInteractor },
- testScope,
- )
-
- whenever(deviceEntryUdfpsInteractor.isUdfpsSupported).thenReturn(MutableStateFlow(false))
- shadeInteractor =
- ShadeInteractorImpl(
- testScope.backgroundScope,
- kosmos.deviceProvisioningInteractor,
- FakeDisableFlagsRepository(),
- mock(),
- keyguardRepository,
- keyguardTransitionInteractor,
- powerInteractor,
- FakeUserSetupRepository(),
- mock(),
- ShadeInteractorLegacyImpl(
- testScope.backgroundScope,
- keyguardRepository,
- SharedNotificationContainerInteractor(
- configurationRepository,
- mContext,
- ResourcesSplitShadeStateController(),
- keyguardInteractor,
- deviceEntryUdfpsInteractor,
- largeScreenHeaderHelperLazy = { largeScreenHeaderHelper }
- ),
- shadeRepository,
- )
- )
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostCoroutinesTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostCoroutinesTest.kt
new file mode 100644
index 0000000..1cd12f0
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostCoroutinesTest.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.statusbar.phone
+
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.doze.DozeHost
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.data.repository.sceneContainerRepository
+import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.testKosmos
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.verify
+
+@SmallTest
+@RunWithLooper(setAsMainLooper = true)
+@RunWith(AndroidJUnit4::class)
+class DozeServiceHostCoroutinesTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+
+ private val sceneContainerRepository = kosmos.sceneContainerRepository
+ private val keyguardInteractor = kosmos.keyguardInteractor
+
+ val underTest =
+ kosmos.dozeServiceHost.apply {
+ initialize(
+ /* centralSurfaces = */ mock(),
+ /* statusBarKeyguardViewManager = */ mock(),
+ /* notificationShadeWindowViewController = */ mock(),
+ /* ambientIndicationContainer = */ mock(),
+ )
+ }
+
+ @Test
+ @EnableSceneContainer
+ fun startStopDozing() =
+ testScope.runTest {
+ val isDozing by collectLastValue(keyguardInteractor.isDozing)
+
+ // GIVEN a callback is set
+ val callback: DozeHost.Callback = mock()
+ underTest.addCallback(callback)
+ // AND we are on the lock screen
+ sceneContainerRepository.changeScene(Scenes.Lockscreen)
+ // AND dozing is not requested yet
+ assertThat(underTest.dozingRequested).isFalse()
+
+ // WHEN dozing started
+ underTest.startDozing()
+ runCurrent()
+
+ // THEN isDozing is set to true
+ assertThat(isDozing).isTrue()
+ assertThat(underTest.dozingRequested).isTrue()
+ verify(callback).onDozingChanged(true)
+
+ // WHEN dozing stopped
+ underTest.stopDozing()
+ runCurrent()
+
+ // THEN isDozing is set to false
+ assertThat(isDozing).isFalse()
+ assertThat(underTest.dozingRequested).isFalse()
+ verify(callback).onDozingChanged(false)
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
index 7e5205b..2114489 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java
@@ -41,7 +41,7 @@
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
-import com.android.systemui.flags.FakeFeatureFlagsClassic;
+import com.android.systemui.flags.DisableSceneContainer;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.DozeInteractor;
import com.android.systemui.shade.NotificationShadeWindowViewController;
@@ -98,13 +98,11 @@
@Mock private DozeHost.Callback mCallback;
@Mock private DozeInteractor mDozeInteractor;
- private final FakeFeatureFlagsClassic mFeatureFlags = new FakeFeatureFlagsClassic();
-
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mDozeServiceHost = new DozeServiceHost(mDozeLog, mPowerManager, mWakefullnessLifecycle,
- mStatusBarStateController, mDeviceProvisionedController, mFeatureFlags,
+ mStatusBarStateController, mDeviceProvisionedController,
mHeadsUpManager, mBatteryController, mScrimController,
() -> mBiometricUnlockController, () -> mAssistManager, mDozeScrimController,
mKeyguardUpdateMonitor, mPulseExpansionHandler, mNotificationShadeWindowController,
@@ -119,6 +117,7 @@
}
@Test
+ @DisableSceneContainer
public void testStartStopDozing() {
mDozeServiceHost.addCallback(mCallback);
when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt
new file mode 100644
index 0000000..632196c
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2024 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.volume.domain.interactor
+
+import android.bluetooth.BluetoothDevice
+import android.graphics.drawable.TestStubDrawable
+import android.media.AudioDeviceInfo
+import android.media.AudioDevicePort
+import android.media.AudioManager
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.settingslib.R
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.media.BluetoothMediaDevice
+import com.android.settingslib.media.MediaDevice
+import com.android.settingslib.media.PhoneMediaDevice
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bluetooth.bluetoothAdapter
+import com.android.systemui.bluetooth.cachedBluetoothDeviceManager
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.volume.data.repository.audioRepository
+import com.android.systemui.volume.domain.model.AudioOutputDevice
+import com.android.systemui.volume.localMediaController
+import com.android.systemui.volume.localMediaRepository
+import com.android.systemui.volume.mediaControllerRepository
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class AudioOutputInteractorTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+
+ lateinit var underTest: AudioOutputInteractor
+
+ @Before
+ fun setUp() {
+ with(kosmos) {
+ underTest = audioOutputInteractor
+
+ with(context.orCreateTestableResources) {
+ addOverride(R.drawable.ic_headphone, testIcon)
+ addOverride(R.drawable.ic_smartphone, testIcon)
+ addOverride(R.drawable.ic_media_speaker_device, testIcon)
+
+ addOverride(com.android.internal.R.drawable.ic_bt_hearing_aid, testIcon)
+ }
+ }
+ }
+
+ @Test
+ fun inCall_builtIn_returnsCommunicationDevice() {
+ with(kosmos) {
+ testScope.runTest {
+ with(audioRepository) {
+ setMode(AudioManager.MODE_IN_CALL)
+ setCommunicationDevice(builtInDevice)
+ }
+
+ val device by collectLastValue(underTest.currentAudioDevice)
+
+ runCurrent()
+
+ assertThat(device).isInstanceOf(AudioOutputDevice.BuiltIn::class.java)
+ assertThat(device!!.icon).isEqualTo(testIcon)
+ assertThat(device!!.name).isEqualTo("built_in")
+ }
+ }
+ }
+
+ @Test
+ fun inCall_wired_returnsCommunicationDevice() {
+ with(kosmos) {
+ testScope.runTest {
+ with(audioRepository) {
+ setMode(AudioManager.MODE_IN_CALL)
+ setCommunicationDevice(wiredDevice)
+ }
+
+ val device by collectLastValue(underTest.currentAudioDevice)
+
+ runCurrent()
+
+ assertThat(device).isInstanceOf(AudioOutputDevice.Wired::class.java)
+ assertThat(device!!.icon).isEqualTo(testIcon)
+ assertThat(device!!.name).isEqualTo("wired")
+ }
+ }
+ }
+
+ @Test
+ fun inCall_bluetooth_returnsCommunicationDevice() {
+ with(kosmos) {
+ testScope.runTest {
+ with(audioRepository) {
+ setMode(AudioManager.MODE_IN_CALL)
+ setCommunicationDevice(btDevice)
+ }
+ val bluetoothDevice: BluetoothDevice = mock {
+ whenever(address).thenReturn(btDevice.address)
+ }
+ val cachedBluetoothDevice: CachedBluetoothDevice = mock {
+ whenever(address).thenReturn(btDevice.address)
+ whenever(name).thenReturn(btDevice.productName.toString())
+ whenever(isHearingAidDevice).thenReturn(true)
+ }
+ whenever(bluetoothAdapter.getRemoteDevice(eq(btDevice.address)))
+ .thenReturn(bluetoothDevice)
+ whenever(cachedBluetoothDeviceManager.findDevice(any()))
+ .thenReturn(cachedBluetoothDevice)
+
+ val device by collectLastValue(underTest.currentAudioDevice)
+
+ runCurrent()
+
+ assertThat(device).isInstanceOf(AudioOutputDevice.Bluetooth::class.java)
+ assertThat(device!!.icon).isEqualTo(testIcon)
+ assertThat(device!!.name).isEqualTo("bt")
+ }
+ }
+ }
+
+ @Test
+ fun notInCall_builtIn_returnsMediaDevice() {
+ with(kosmos) {
+ testScope.runTest {
+ audioRepository.setMode(AudioManager.MODE_NORMAL)
+ mediaControllerRepository.setActiveSessions(listOf(localMediaController))
+ localMediaRepository.updateCurrentConnectedDevice(builtInMediaDevice)
+
+ val device by collectLastValue(underTest.currentAudioDevice)
+
+ runCurrent()
+
+ assertThat(device).isInstanceOf(AudioOutputDevice.BuiltIn::class.java)
+ assertThat(device!!.icon).isEqualTo(testIcon)
+ assertThat(device!!.name).isEqualTo("built_in_media")
+ }
+ }
+ }
+
+ @Test
+ fun notInCall_wired_returnsMediaDevice() {
+ with(kosmos) {
+ testScope.runTest {
+ audioRepository.setMode(AudioManager.MODE_NORMAL)
+ mediaControllerRepository.setActiveSessions(listOf(localMediaController))
+ localMediaRepository.updateCurrentConnectedDevice(wiredMediaDevice)
+
+ val device by collectLastValue(underTest.currentAudioDevice)
+
+ runCurrent()
+
+ assertThat(device).isInstanceOf(AudioOutputDevice.Wired::class.java)
+ assertThat(device!!.icon).isEqualTo(testIcon)
+ assertThat(device!!.name).isEqualTo("wired_media")
+ }
+ }
+ }
+
+ @Test
+ fun notInCall_bluetooth_returnsMediaDevice() {
+ with(kosmos) {
+ testScope.runTest {
+ audioRepository.setMode(AudioManager.MODE_NORMAL)
+ mediaControllerRepository.setActiveSessions(listOf(localMediaController))
+ localMediaRepository.updateCurrentConnectedDevice(bluetoothMediaDevice)
+
+ val device by collectLastValue(underTest.currentAudioDevice)
+
+ runCurrent()
+
+ assertThat(device).isInstanceOf(AudioOutputDevice.Bluetooth::class.java)
+ assertThat(device!!.icon).isEqualTo(testIcon)
+ assertThat(device!!.name).isEqualTo("bt_media")
+ }
+ }
+ }
+
+ private companion object {
+ val testIcon = TestStubDrawable()
+ val builtInDevice =
+ AudioDeviceInfo(
+ AudioDevicePort.createForTesting(
+ AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
+ "built_in",
+ ""
+ )
+ )
+ val wiredDevice =
+ AudioDeviceInfo(
+ AudioDevicePort.createForTesting(AudioDeviceInfo.TYPE_WIRED_HEADPHONES, "wired", "")
+ )
+ val btDevice =
+ AudioDeviceInfo(
+ AudioDevicePort.createForTesting(
+ AudioDeviceInfo.TYPE_BLE_HEADSET,
+ "bt",
+ "test_address"
+ )
+ )
+ val builtInMediaDevice: MediaDevice =
+ mock<PhoneMediaDevice> {
+ whenever(name).thenReturn("built_in_media")
+ whenever(icon).thenReturn(testIcon)
+ }
+ val wiredMediaDevice: MediaDevice =
+ mock<PhoneMediaDevice> {
+ whenever(deviceType)
+ .thenReturn(MediaDevice.MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE)
+ whenever(name).thenReturn("wired_media")
+ whenever(icon).thenReturn(testIcon)
+ }
+ val bluetoothMediaDevice: MediaDevice =
+ mock<BluetoothMediaDevice> {
+ whenever(name).thenReturn("bt_media")
+ whenever(icon).thenReturn(testIcon)
+ val cachedBluetoothDevice: CachedBluetoothDevice = mock {
+ whenever(isHearingAidDevice).thenReturn(true)
+ }
+ whenever(cachedDevice).thenReturn(cachedBluetoothDevice)
+ }
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioVolumeInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioVolumeInteractorTest.kt
index fa79e7f..675136c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioVolumeInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioVolumeInteractorTest.kt
@@ -31,7 +31,7 @@
import com.android.systemui.statusbar.notification.domain.interactor.notificationsSoundPolicyInteractor
import com.android.systemui.statusbar.notification.domain.interactor.notificationsSoundPolicyRepository
import com.android.systemui.testKosmos
-import com.android.systemui.volume.audioRepository
+import com.android.systemui.volume.data.repository.audioRepository
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartableTest.kt
index 8bb3672..89acbc8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/startable/AudioModeLoggerStartableTest.kt
@@ -25,8 +25,8 @@
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
-import com.android.systemui.volume.audioModeInteractor
-import com.android.systemui.volume.audioRepository
+import com.android.systemui.volume.data.repository.audioRepository
+import com.android.systemui.volume.domain.interactor.audioModeInteractor
import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -56,7 +56,7 @@
AudioModeLoggerStartable(
applicationCoroutineScope,
uiEventLogger,
- audioModeInteractor
+ audioModeInteractor,
)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt
index da0a229..96b4dae 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/MediaOutputAvailabilityCriteriaTest.kt
@@ -24,8 +24,8 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
-import com.android.systemui.volume.audioModeInteractor
-import com.android.systemui.volume.audioRepository
+import com.android.systemui.volume.data.repository.audioRepository
+import com.android.systemui.volume.domain.interactor.audioModeInteractor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
diff --git a/packages/SystemUI/res/anim/shortcut_helper_close_anim.xml b/packages/SystemUI/res/anim/shortcut_helper_close_anim.xml
new file mode 100644
index 0000000..47fd78a
--- /dev/null
+++ b/packages/SystemUI/res/anim/shortcut_helper_close_anim.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@android:anim/accelerate_interpolator"
+ android:zAdjustment="top">
+
+ <translate
+ android:fromYDelta="0"
+ android:toYDelta="100%"
+ android:duration="@android:integer/config_shortAnimTime" />
+</set>
diff --git a/packages/SystemUI/res/anim/shortcut_helper_launch_anim.xml b/packages/SystemUI/res/anim/shortcut_helper_launch_anim.xml
new file mode 100644
index 0000000..77edf58
--- /dev/null
+++ b/packages/SystemUI/res/anim/shortcut_helper_launch_anim.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 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.
+ -->
+
+<!-- Animation for when a dock window at the bottom of the screen is entering. -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+ android:zAdjustment="top">
+
+ <translate android:fromYDelta="100%"
+ android:toYDelta="0"
+ android:startOffset="@android:integer/config_shortAnimTime"
+ android:duration="@android:integer/config_mediumAnimTime"/>
+</set>
diff --git a/packages/SystemUI/res/layout/activity_keyboard_shortcut_helper.xml b/packages/SystemUI/res/layout/activity_keyboard_shortcut_helper.xml
new file mode 100644
index 0000000..292e496
--- /dev/null
+++ b/packages/SystemUI/res/layout/activity_keyboard_shortcut_helper.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/shortcut_helper_sheet_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:id="@+id/shortcut_helper_sheet"
+ style="@style/Widget.Material3.BottomSheet"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
+
+ <!-- Drag handle for accessibility -->
+ <com.google.android.material.bottomsheet.BottomSheetDragHandleView
+ android:id="@+id/drag_handle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:textAppearance="?textAppearanceDisplayLarge"
+ android:background="?colorTertiaryContainer"
+ android:text="Shortcut Helper Content" />
+ </LinearLayout>
+</androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/packages/SystemUI/res/layout/combined_qs_header.xml b/packages/SystemUI/res/layout/combined_qs_header.xml
index beb481a..b9ef88e 100644
--- a/packages/SystemUI/res/layout/combined_qs_header.xml
+++ b/packages/SystemUI/res/layout/combined_qs_header.xml
@@ -129,7 +129,7 @@
android:id="@+id/hover_system_icons_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_gravity="right|center_vertical"
+ android:layout_gravity="end|center_vertical"
android:gravity="center_vertical"
android:paddingStart="@dimen/hover_system_icons_container_padding_start"
android:paddingEnd="@dimen/hover_system_icons_container_padding_end"
diff --git a/packages/SystemUI/res/layout/screenshot_shelf.xml b/packages/SystemUI/res/layout/screenshot_shelf.xml
index 6a5b999f..26d3f43 100644
--- a/packages/SystemUI/res/layout/screenshot_shelf.xml
+++ b/packages/SystemUI/res/layout/screenshot_shelf.xml
@@ -147,4 +147,11 @@
<include layout="@layout/screenshot_work_profile_first_run" />
<include layout="@layout/screenshot_detection_notice" />
</FrameLayout>
+ <ImageView
+ android:id="@+id/screenshot_flash"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone"
+ android:elevation="12dp"
+ android:src="@android:color/white"/>
</com.android.systemui.screenshot.ui.ScreenshotShelfView>
diff --git a/packages/SystemUI/res/values-night/styles.xml b/packages/SystemUI/res/values-night/styles.xml
index 291f8a2..546bf1c 100644
--- a/packages/SystemUI/res/values-night/styles.xml
+++ b/packages/SystemUI/res/values-night/styles.xml
@@ -72,4 +72,8 @@
<item name="android:textColor">@color/material_dynamic_secondary80</item>
</style>
+ <style name="ShortcutHelperTheme" parent="@style/ShortcutHelperThemeCommon">
+ <item name="android:windowLightNavigationBar">false</item>
+ </style>
+
</resources>
diff --git a/packages/SystemUI/res/values-xlarge-land/config.xml b/packages/SystemUI/res/values-xlarge-land/config.xml
new file mode 100644
index 0000000..5e4304e
--- /dev/null
+++ b/packages/SystemUI/res/values-xlarge-land/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 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.
+ -->
+
+<resources>
+ <item name="shortcut_helper_screen_width_fraction" format="float" type="dimen">0.8</item>
+</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 4a73d85..19273ec 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -1010,4 +1010,7 @@
<!-- Whether volume panel should use the large screen layout or not -->
<bool name="volume_panel_is_large_screen">false</bool>
+
+ <!-- The width of the shortcut helper container, as a fraction of the screen's width. -->
+ <item name="shortcut_helper_screen_width_fraction" format="float" type="dimen">1.0</item>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 9aff9fd..b8e78a4 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1718,6 +1718,11 @@
<!-- Accessibility label for available satellite connection [CHAR LIMIT=NONE] -->
<string name="accessibility_status_bar_satellite_available">Satellite, connection available</string>
+ <!-- Text displayed indicating that the user is connected to a satellite signal. -->
+ <string name="satellite_connected_carrier_text">Connected to satellite</string>
+ <!-- Text displayed indicating that the user is not connected to a satellite signal. -->
+ <string name="satellite_not_connected_carrier_text">Not connected to satellite</string>
+
<!-- Accessibility label for managed profile icon (not shown on screen) [CHAR LIMIT=NONE] -->
<string name="accessibility_managed_profile">Work profile</string>
@@ -1991,7 +1996,7 @@
<string name="keyboard_shortcut_clear_text">Clear search query</string>
<!-- The title for keyboard shortcut search list [CHAR LIMIT=25] -->
<string name="keyboard_shortcut_search_list_title">Keyboard Shortcuts</string>
- <!-- The hint for keyboard shortcut search list [CHAR LIMIT=25] -->
+ <!-- The hint for keyboard shortcut search list [CHAR LIMIT=50] -->
<string name="keyboard_shortcut_search_list_hint">Search shortcuts</string>
<!-- The description for no shortcuts results [CHAR LIMIT=25] -->
<string name="keyboard_shortcut_search_list_no_result">No shortcuts found</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 2c9006e..3d57111 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -1654,4 +1654,28 @@
<style name="Theme.SystemUI.Dialog.StickyKeys" parent="@style/Theme.SystemUI.Dialog">
<item name="android:colorBackground">@color/transparent</item>
</style>
+
+ <style name="ShortcutHelperAnimation" parent="@android:style/Animation.Activity">
+ <item name="android:activityOpenEnterAnimation">@anim/shortcut_helper_launch_anim</item>
+ <item name="android:taskOpenEnterAnimation">@anim/shortcut_helper_launch_anim</item>
+ <item name="android:activityOpenExitAnimation">@anim/shortcut_helper_close_anim</item>
+ <item name="android:taskOpenExitAnimation">@anim/shortcut_helper_close_anim</item>
+ </style>
+
+ <style name="ShortcutHelperThemeCommon" parent="@style/Theme.Material3.DynamicColors.DayNight">
+ <item name="android:windowAnimationStyle">@style/ShortcutHelperAnimation</item>
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:backgroundDimEnabled">true</item>
+ <item name="android:statusBarColor">@android:color/transparent</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:navigationBarColor">@android:color/transparent</item>
+ <item name="android:windowLayoutInDisplayCutoutMode">always</item>
+ <item name="enableEdgeToEdge">true</item>
+ </style>
+
+ <style name="ShortcutHelperTheme" parent="@style/ShortcutHelperThemeCommon">
+ <item name="android:windowLightNavigationBar">true</item>
+ </style>
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java
index b9b8fbe..5647b0b 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextManager.java
@@ -19,6 +19,7 @@
import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_ACTIVE_DATA_SUB_CHANGED;
import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_ON_TELEPHONY_CAPABLE;
import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_REFRESH_CARRIER_INFO;
+import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_SATELLITE_CHANGED;
import static com.android.keyguard.logging.CarrierTextManagerLogger.REASON_SIM_ERROR_STATE_CHANGED;
import android.content.Context;
@@ -43,17 +44,22 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.res.R;
+import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModel;
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository;
import com.android.systemui.telephony.TelephonyListenerManager;
+import com.android.systemui.util.kotlin.JavaAdapter;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.inject.Inject;
+import kotlinx.coroutines.Job;
+
/**
* Controller that generates text including the carrier names and/or the status of all the SIM
* interfaces in the device. Through a callback, the updates can be retrieved either as a list or
@@ -77,10 +83,17 @@
protected KeyguardUpdateMonitor mKeyguardUpdateMonitor;
private final CarrierTextManagerLogger mLogger;
private final WifiRepository mWifiRepository;
+ private final DeviceBasedSatelliteViewModel mDeviceBasedSatelliteViewModel;
+ private final JavaAdapter mJavaAdapter;
private final boolean[] mSimErrorState;
private final int mSimSlotsNumber;
@Nullable // Check for nullability before dispatching
private CarrierTextCallback mCarrierTextCallback;
+ @Nullable
+ private Job mSatelliteConnectionJob;
+
+ @Nullable private String mSatelliteCarrierText;
+
private final Context mContext;
private final TelephonyManager mTelephonyManager;
private final CharSequence mSeparator;
@@ -178,6 +191,8 @@
boolean showAirplaneMode,
boolean showMissingSim,
WifiRepository wifiRepository,
+ DeviceBasedSatelliteViewModel deviceBasedSatelliteViewModel,
+ JavaAdapter javaAdapter,
TelephonyManager telephonyManager,
TelephonyListenerManager telephonyListenerManager,
WakefulnessLifecycle wakefulnessLifecycle,
@@ -192,6 +207,8 @@
mShowAirplaneMode = showAirplaneMode;
mShowMissingSim = showMissingSim;
mWifiRepository = wifiRepository;
+ mDeviceBasedSatelliteViewModel = deviceBasedSatelliteViewModel;
+ mJavaAdapter = javaAdapter;
mTelephonyManager = telephonyManager;
mSeparator = separator;
mTelephonyListenerManager = telephonyListenerManager;
@@ -282,6 +299,11 @@
mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
});
mTelephonyListenerManager.addActiveDataSubscriptionIdListener(mPhoneStateListener);
+ cancelSatelliteCollectionJob(/* reason= */ "Starting new job");
+ mSatelliteConnectionJob =
+ mJavaAdapter.alwaysCollectFlow(
+ mDeviceBasedSatelliteViewModel.getCarrierText(),
+ this::onSatelliteCarrierTextChanged);
} else {
// Don't listen and clear out the text when the device isn't a phone.
mMainExecutor.execute(() -> callback.updateCarrierInfo(
@@ -294,6 +316,7 @@
mWakefulnessLifecycle.removeObserver(mWakefulnessObserver);
});
mTelephonyListenerManager.removeActiveDataSubscriptionIdListener(mPhoneStateListener);
+ cancelSatelliteCollectionJob(/* reason= */ "Stopping listening");
}
}
@@ -311,6 +334,12 @@
return mKeyguardUpdateMonitor.getFilteredSubscriptionInfo();
}
+ private void onSatelliteCarrierTextChanged(@Nullable String text) {
+ mLogger.logUpdateCarrierTextForReason(REASON_SATELLITE_CHANGED);
+ mSatelliteCarrierText = text;
+ updateCarrierText();
+ }
+
protected void updateCarrierText() {
Trace.beginSection("CarrierTextManager#updateCarrierText");
boolean allSimsMissing = true;
@@ -411,6 +440,12 @@
airplaneMode = true;
}
+ String currentSatelliteText = mSatelliteCarrierText;
+ if (currentSatelliteText != null) {
+ mLogger.logUsingSatelliteText(currentSatelliteText);
+ displayText = currentSatelliteText;
+ }
+
final CarrierTextCallbackInfo info = new CarrierTextCallbackInfo(
displayText,
carrierNames,
@@ -616,11 +651,20 @@
return list;
}
+ private void cancelSatelliteCollectionJob(String reason) {
+ Job job = mSatelliteConnectionJob;
+ if (job != null) {
+ job.cancel(new CancellationException(reason));
+ }
+ }
+
/** Injectable Buildeer for {@#link CarrierTextManager}. */
public static class Builder {
private final Context mContext;
private final String mSeparator;
private final WifiRepository mWifiRepository;
+ private final DeviceBasedSatelliteViewModel mDeviceBasedSatelliteViewModel;
+ private final JavaAdapter mJavaAdapter;
private final TelephonyManager mTelephonyManager;
private final TelephonyListenerManager mTelephonyListenerManager;
private final WakefulnessLifecycle mWakefulnessLifecycle;
@@ -637,6 +681,8 @@
Context context,
@Main Resources resources,
@Nullable WifiRepository wifiRepository,
+ DeviceBasedSatelliteViewModel deviceBasedSatelliteViewModel,
+ JavaAdapter javaAdapter,
TelephonyManager telephonyManager,
TelephonyListenerManager telephonyListenerManager,
WakefulnessLifecycle wakefulnessLifecycle,
@@ -648,6 +694,8 @@
mSeparator = resources.getString(
com.android.internal.R.string.kg_text_message_separator);
mWifiRepository = wifiRepository;
+ mDeviceBasedSatelliteViewModel = deviceBasedSatelliteViewModel;
+ mJavaAdapter = javaAdapter;
mTelephonyManager = telephonyManager;
mTelephonyListenerManager = telephonyListenerManager;
mWakefulnessLifecycle = wakefulnessLifecycle;
@@ -682,9 +730,20 @@
public CarrierTextManager build() {
mLogger.setLocation(mDebugLocation);
return new CarrierTextManager(
- mContext, mSeparator, mShowAirplaneMode, mShowMissingSim, mWifiRepository,
- mTelephonyManager, mTelephonyListenerManager, mWakefulnessLifecycle,
- mMainExecutor, mBgExecutor, mKeyguardUpdateMonitor, mLogger);
+ mContext,
+ mSeparator,
+ mShowAirplaneMode,
+ mShowMissingSim,
+ mWifiRepository,
+ mDeviceBasedSatelliteViewModel,
+ mJavaAdapter,
+ mTelephonyManager,
+ mTelephonyListenerManager,
+ mWakefulnessLifecycle,
+ mMainExecutor,
+ mBgExecutor,
+ mKeyguardUpdateMonitor,
+ mLogger);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index e8e1cab..4ddf3c9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -39,7 +39,6 @@
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.hardware.biometrics.BiometricRequestConstants;
import android.media.AudioManager;
import android.metrics.LogMaker;
import android.os.SystemClock;
@@ -73,9 +72,6 @@
import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.biometrics.FaceAuthAccessibilityDelegate;
-import com.android.systemui.biometrics.SideFpsController;
-import com.android.systemui.biometrics.SideFpsUiRequestSource;
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor;
import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.classifier.FalsingA11yDelegate;
@@ -103,15 +99,14 @@
import dagger.Lazy;
+import kotlinx.coroutines.Job;
+
import java.io.File;
import java.util.Arrays;
-import java.util.Optional;
import javax.inject.Inject;
import javax.inject.Provider;
-import kotlinx.coroutines.Job;
-
/** Controller for {@link KeyguardSecurityContainer} */
@KeyguardBouncerScope
public class KeyguardSecurityContainerController extends ViewController<KeyguardSecurityContainer>
@@ -135,7 +130,6 @@
private final GlobalSettings mGlobalSettings;
private final FeatureFlags mFeatureFlags;
private final SessionTracker mSessionTracker;
- private final Optional<SideFpsController> mSideFpsController;
private final FalsingA11yDelegate mFalsingA11yDelegate;
private final DeviceEntryFaceAuthInteractor mDeviceEntryFaceAuthInteractor;
private final BouncerMessageInteractor mBouncerMessageInteractor;
@@ -457,7 +451,6 @@
FeatureFlags featureFlags,
GlobalSettings globalSettings,
SessionTracker sessionTracker,
- Optional<SideFpsController> sideFpsController,
FalsingA11yDelegate falsingA11yDelegate,
TelephonyManager telephonyManager,
ViewMediatorCallback viewMediatorCallback,
@@ -491,11 +484,6 @@
mFeatureFlags = featureFlags;
mGlobalSettings = globalSettings;
mSessionTracker = sessionTracker;
- if (SideFpsControllerRefactor.isEnabled()) {
- mSideFpsController = Optional.empty();
- } else {
- mSideFpsController = sideFpsController;
- }
mFalsingA11yDelegate = falsingA11yDelegate;
mTelephonyManager = telephonyManager;
mViewMediatorCallback = viewMediatorCallback;
@@ -578,28 +566,6 @@
mView.clearFocus();
}
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- /**
- * Shows and hides the side finger print sensor animation.
- *
- * @param isVisible sets whether we show or hide the side fps animation
- */
- public void updateSideFpsVisibility(boolean isVisible) {
- SideFpsControllerRefactor.assertInLegacyMode();
- if (!mSideFpsController.isPresent()) {
- return;
- }
-
- if (isVisible) {
- mSideFpsController.get().show(
- SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricRequestConstants.REASON_AUTH_KEYGUARD
- );
- } else {
- mSideFpsController.get().hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- }
- }
-
/**
* Shows the primary security screen for the user. This will be either the multi-selector
* or the user's security method.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 8c51a4e..519622e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -42,7 +42,6 @@
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_OPENED;
-import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_UNKNOWN;
import android.annotation.AnyThread;
import android.annotation.MainThread;
@@ -1868,7 +1867,9 @@
@Override
public void onPostureChanged(@DevicePostureInt int posture) {
if (posture == DEVICE_POSTURE_OPENED) {
- mLogger.d("Posture changed to open - attempting to request active unlock");
+ mLogger.d("Posture changed to open - attempting to request active"
+ + " unlock and run face auth");
+ getFaceAuthInteractor().onDeviceUnfolded();
requestActiveUnlockFromWakeReason(PowerManager.WAKE_REASON_UNFOLD_DEVICE,
false);
}
@@ -2434,9 +2435,7 @@
updateFingerprintListeningState(BIOMETRIC_ACTION_START);
}
});
- if (mConfigFaceAuthSupportedPosture != DEVICE_POSTURE_UNKNOWN) {
- mDevicePostureController.addCallback(mPostureCallback);
- }
+ mDevicePostureController.addCallback(mPostureCallback);
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
mTaskStackChangeListeners.registerTaskStackListener(mTaskStackListener);
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
index afea224..4bbc2d6 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java
@@ -16,23 +16,14 @@
package com.android.keyguard.dagger;
-import static com.android.systemui.biometrics.SideFpsControllerKt.hasSideFpsSensor;
-
-import android.annotation.Nullable;
-import android.hardware.fingerprint.FingerprintManager;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import com.android.keyguard.KeyguardSecurityContainer;
import com.android.keyguard.KeyguardSecurityViewFlipper;
-import com.android.systemui.res.R;
-import com.android.systemui.biometrics.SideFpsController;
-import com.android.systemui.dagger.qualifiers.RootView;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
-
-import java.util.Optional;
-
-import javax.inject.Provider;
+import com.android.systemui.dagger.qualifiers.RootView;
+import com.android.systemui.res.R;
import dagger.Module;
import dagger.Provides;
@@ -62,16 +53,4 @@
KeyguardSecurityContainer containerView) {
return containerView.findViewById(R.id.view_flipper);
}
-
- /** Provides {@link SideFpsController} if the device has the side fingerprint sensor. */
- @Provides
- @KeyguardBouncerScope
- static Optional<SideFpsController> providesOptionalSidefpsController(
- @Nullable FingerprintManager fingerprintManager,
- Provider<SideFpsController> sidefpsControllerProvider) {
- if (!hasSideFpsSensor(fingerprintManager)) {
- return Optional.empty();
- }
- return Optional.of(sidefpsControllerProvider.get());
- }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/CarrierTextManagerLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/CarrierTextManagerLogger.kt
index cb474d3..48fea55 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/CarrierTextManagerLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/CarrierTextManagerLogger.kt
@@ -77,6 +77,15 @@
)
}
+ fun logUsingSatelliteText(satelliteText: String) {
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ { str1 = satelliteText },
+ { "┣ updateCarrierText: using satellite text. text=$str1" },
+ )
+ }
+
/** De-structures the info object so that we don't have to generate new strings */
fun logCallbackSentFromUpdate(info: CarrierTextCallbackInfo) {
buffer.log(
@@ -129,6 +138,7 @@
const val REASON_ON_TELEPHONY_CAPABLE = 2
const val REASON_SIM_ERROR_STATE_CHANGED = 3
const val REASON_ACTIVE_DATA_SUB_CHANGED = 4
+ const val REASON_SATELLITE_CHANGED = 5
@Retention(AnnotationRetention.SOURCE)
@IntDef(
@@ -138,6 +148,7 @@
REASON_ON_TELEPHONY_CAPABLE,
REASON_SIM_ERROR_STATE_CHANGED,
REASON_ACTIVE_DATA_SUB_CHANGED,
+ REASON_SATELLITE_CHANGED,
]
)
annotation class CarrierTextRefreshReason
@@ -148,6 +159,7 @@
REASON_ON_TELEPHONY_CAPABLE -> "ON_TELEPHONY_CAPABLE"
REASON_SIM_ERROR_STATE_CHANGED -> "SIM_ERROR_STATE_CHANGED"
REASON_ACTIVE_DATA_SUB_CHANGED -> "ACTIVE_DATA_SUB_CHANGED"
+ REASON_SATELLITE_CHANGED -> "SATELLITE_CHANGED"
else -> "unknown"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 08d45fa..4b07402 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -299,6 +299,7 @@
int serviceIndex = 0;
do {
+ startedAny = false;
queue = nextQueue;
nextQueue = new ArrayDeque<>(startables.size());
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java b/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java
index 7e94804..5c75a49 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java
@@ -94,7 +94,7 @@
.setOneHanded(mWMComponent.getOneHanded())
.setBubbles(mWMComponent.getBubbles())
.setTaskViewFactory(mWMComponent.getTaskViewFactory())
- .setTransitions(mWMComponent.getTransitions())
+ .setShellTransitions(mWMComponent.getShellTransitions())
.setKeyguardTransitions(mWMComponent.getKeyguardTransitions())
.setStartingSurface(mWMComponent.getStartingSurface())
.setDisplayAreaHelper(mWMComponent.getDisplayAreaHelper())
@@ -115,7 +115,7 @@
.setOneHanded(Optional.ofNullable(null))
.setBubbles(Optional.ofNullable(null))
.setTaskViewFactory(Optional.ofNullable(null))
- .setTransitions(new ShellTransitions() {})
+ .setShellTransitions(new ShellTransitions() {})
.setKeyguardTransitions(new KeyguardTransitions() {})
.setDisplayAreaHelper(Optional.ofNullable(null))
.setStartingSurface(Optional.ofNullable(null))
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/TEST_MAPPING b/packages/SystemUI/src/com/android/systemui/accessibility/TEST_MAPPING
index be26b43..17813cf 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/TEST_MAPPING
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/TEST_MAPPING
@@ -20,5 +20,10 @@
}
]
}
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsAccessibilityServiceTestCases"
+ }
]
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index 9837e36..e66261c 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -726,11 +726,11 @@
int windowWidth = mMagnificationFrame.width() + 2 * mMirrorSurfaceMargin;
int windowHeight = mMagnificationFrame.height() + 2 * mMirrorSurfaceMargin;
- // TODO delete TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, it shouldn't be needed anymore
-
+ // TODO: b/335440685 - Move to TYPE_ACCESSIBILITY_OVERLAY after the issues with
+ // that type preventing swipe to navigate are resolved.
LayoutParams params = new LayoutParams(
windowWidth, windowHeight,
- LayoutParams.TYPE_ACCESSIBILITY_OVERLAY,
+ LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,
LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSPARENT);
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.java
index d0f08f5..85aeb27 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/BouncerSwipeTouchHandler.java
@@ -27,6 +27,7 @@
import android.view.MotionEvent;
import android.view.VelocityTracker;
+import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.UiEvent;
@@ -94,13 +95,11 @@
private Boolean mCapture;
private Boolean mExpanded;
- private boolean mBouncerInitiallyShowing;
-
private TouchSession mTouchSession;
- private ValueAnimatorCreator mValueAnimatorCreator;
+ private final ValueAnimatorCreator mValueAnimatorCreator;
- private VelocityTrackerFactory mVelocityTrackerFactory;
+ private final VelocityTrackerFactory mVelocityTrackerFactory;
private final UiEventLogger mUiEventLogger;
@@ -118,17 +117,12 @@
private final GestureDetector.OnGestureListener mOnGestureListener =
new GestureDetector.SimpleOnGestureListener() {
@Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
+ public boolean onScroll(MotionEvent e1, @NonNull MotionEvent e2, float distanceX,
float distanceY) {
if (mCapture == null) {
- mBouncerInitiallyShowing = mCentralSurfaces
- .map(CentralSurfaces::isBouncerShowing)
- .orElse(false);
-
if (Flags.dreamOverlayBouncerSwipeDirectionFiltering()) {
mCapture = Math.abs(distanceY) > Math.abs(distanceX)
- && ((distanceY < 0 && mBouncerInitiallyShowing)
- || (distanceY > 0 && !mBouncerInitiallyShowing));
+ && distanceY > 0;
} else {
// If the user scrolling favors a vertical direction, begin capturing
// scrolls.
@@ -146,13 +140,8 @@
return false;
}
- // Don't set expansion for downward scroll when the bouncer is hidden.
- if (!mBouncerInitiallyShowing && (e1.getY() < e2.getY())) {
- return true;
- }
-
- // Don't set expansion for upward scroll when the bouncer is shown.
- if (mBouncerInitiallyShowing && (e1.getY() > e2.getY())) {
+ // Don't set expansion for downward scroll.
+ if (e1.getY() < e2.getY()) {
return true;
}
@@ -176,8 +165,7 @@
final float dragDownAmount = e2.getY() - e1.getY();
final float screenTravelPercentage = Math.abs(e1.getY() - e2.getY())
/ mTouchSession.getBounds().height();
- setPanelExpansion(mBouncerInitiallyShowing
- ? screenTravelPercentage : 1 - screenTravelPercentage);
+ setPanelExpansion(1 - screenTravelPercentage);
return true;
}
};
@@ -223,9 +211,9 @@
LockPatternUtils lockPatternUtils,
UserTracker userTracker,
@Named(BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING)
- FlingAnimationUtils flingAnimationUtils,
+ FlingAnimationUtils flingAnimationUtils,
@Named(BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING)
- FlingAnimationUtils flingAnimationUtilsClosing,
+ FlingAnimationUtils flingAnimationUtilsClosing,
@Named(BouncerSwipeModule.SWIPE_TO_BOUNCER_START_REGION) float swipeRegionPercentage,
@Named(BouncerSwipeModule.MIN_BOUNCER_ZONE_SCREEN_PERCENTAGE) float minRegionPercentage,
UiEventLogger uiEventLogger) {
@@ -247,17 +235,13 @@
public void getTouchInitiationRegion(Rect bounds, Region region, Rect exclusionRect) {
final int width = bounds.width();
final int height = bounds.height();
- final float minBouncerHeight = height * mMinBouncerZoneScreenPercentage;
final int minAllowableBottom = Math.round(height * (1 - mMinBouncerZoneScreenPercentage));
- final boolean isBouncerShowing =
- mCentralSurfaces.map(CentralSurfaces::isBouncerShowing).orElse(false);
- final Rect normalRegion = isBouncerShowing
- ? new Rect(0, 0, width, Math.round(height * mBouncerZoneScreenPercentage))
- : new Rect(0, Math.round(height * (1 - mBouncerZoneScreenPercentage)),
- width, height);
+ final Rect normalRegion = new Rect(0,
+ Math.round(height * (1 - mBouncerZoneScreenPercentage)),
+ width, height);
- if (!isBouncerShowing && exclusionRect != null) {
+ if (exclusionRect != null) {
int lowestBottom = Math.min(Math.max(0, exclusionRect.bottom), minAllowableBottom);
normalRegion.top = Math.max(normalRegion.top, lowestBottom);
}
@@ -322,8 +306,7 @@
: KeyguardBouncerConstants.EXPANSION_HIDDEN;
// Log the swiping up to show Bouncer event.
- if (!mBouncerInitiallyShowing
- && expansion == KeyguardBouncerConstants.EXPANSION_VISIBLE) {
+ if (expansion == KeyguardBouncerConstants.EXPANSION_VISIBLE) {
mUiEventLogger.log(DreamEvent.DREAM_SWIPED);
}
@@ -335,17 +318,15 @@
}
}
- private ValueAnimator createExpansionAnimator(float targetExpansion, float expansionHeight) {
+ private ValueAnimator createExpansionAnimator(float targetExpansion) {
final ValueAnimator animator =
mValueAnimatorCreator.create(mCurrentExpansion, targetExpansion);
animator.addUpdateListener(
animation -> {
float expansionFraction = (float) animation.getAnimatedValue();
- float dragDownAmount = expansionFraction * expansionHeight;
setPanelExpansion(expansionFraction);
});
- if (!mBouncerInitiallyShowing
- && targetExpansion == KeyguardBouncerConstants.EXPANSION_VISIBLE) {
+ if (targetExpansion == KeyguardBouncerConstants.EXPANSION_VISIBLE) {
animator.addListener(
new AnimatorListenerAdapter() {
@Override
@@ -381,8 +362,7 @@
final float viewHeight = mTouchSession.getBounds().height();
final float currentHeight = viewHeight * mCurrentExpansion;
final float targetHeight = viewHeight * expansion;
- final float expansionHeight = targetHeight - currentHeight;
- final ValueAnimator animator = createExpansionAnimator(expansion, expansionHeight);
+ final ValueAnimator animator = createExpansionAnimator(expansion);
if (expansion == KeyguardBouncerConstants.EXPANSION_HIDDEN) {
// Hides the bouncer, i.e., fully expands the space above the bouncer.
mFlingAnimationUtilsClosing.apply(animator, currentHeight, targetHeight, velocity,
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/ShadeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/ShadeTouchHandler.java
index 9ef9938..9c7fc9d 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/touch/ShadeTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/ShadeTouchHandler.java
@@ -23,7 +23,8 @@
import android.view.GestureDetector;
import android.view.MotionEvent;
-import com.android.systemui.shade.ShadeViewController;
+import androidx.annotation.NonNull;
+
import com.android.systemui.statusbar.phone.CentralSurfaces;
import java.util.Optional;
@@ -37,29 +38,34 @@
*/
public class ShadeTouchHandler implements TouchHandler {
private final Optional<CentralSurfaces> mSurfaces;
- private final ShadeViewController mShadeViewController;
private final int mInitiationHeight;
+ /**
+ * Tracks whether or not we are capturing a given touch. Will be null before and after a touch.
+ */
+ private Boolean mCapture;
+
@Inject
ShadeTouchHandler(Optional<CentralSurfaces> centralSurfaces,
- ShadeViewController shadeViewController,
@Named(NOTIFICATION_SHADE_GESTURE_INITIATION_HEIGHT) int initiationHeight) {
mSurfaces = centralSurfaces;
- mShadeViewController = shadeViewController;
mInitiationHeight = initiationHeight;
}
@Override
public void onSessionStart(TouchSession session) {
- if (mSurfaces.map(CentralSurfaces::isBouncerShowing).orElse(false)) {
+ if (mSurfaces.isEmpty()) {
session.pop();
return;
}
- session.registerInputListener(ev -> {
- mShadeViewController.handleExternalTouch((MotionEvent) ev);
+ session.registerCallback(() -> mCapture = null);
+ session.registerInputListener(ev -> {
if (ev instanceof MotionEvent) {
+ if (mCapture != null && mCapture) {
+ mSurfaces.get().handleExternalShadeWindowTouch((MotionEvent) ev);
+ }
if (((MotionEvent) ev).getAction() == MotionEvent.ACTION_UP) {
session.pop();
}
@@ -68,15 +74,25 @@
session.registerGestureListener(new GestureDetector.SimpleOnGestureListener() {
@Override
- public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
+ public boolean onScroll(MotionEvent e1, @NonNull MotionEvent e2, float distanceX,
float distanceY) {
- return true;
+ if (mCapture == null) {
+ // Only capture swipes that are going downwards.
+ mCapture = Math.abs(distanceY) > Math.abs(distanceX) && distanceY < 0;
+ if (mCapture) {
+ // Send the initial touches over, as the input listener has already
+ // processed these touches.
+ mSurfaces.get().handleExternalShadeWindowTouch(e1);
+ mSurfaces.get().handleExternalShadeWindowTouch(e2);
+ }
+ }
+ return mCapture;
}
@Override
- public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
+ public boolean onFling(MotionEvent e1, @NonNull MotionEvent e2, float velocityX,
float velocityY) {
- return true;
+ return mCapture;
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt b/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt
index a667de2..970699f 100644
--- a/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt
@@ -28,8 +28,9 @@
import android.os.UserHandle
import android.util.Log
import com.android.app.tracing.traceSection
-import com.android.systemui.Flags.communalHub
import com.android.systemui.backup.BackupHelper.Companion.ACTION_RESTORE_FINISHED
+import com.android.systemui.communal.data.backup.CommunalBackupHelper
+import com.android.systemui.communal.data.backup.CommunalBackupUtils
import com.android.systemui.communal.domain.backup.CommunalPrefsBackupHelper
import com.android.systemui.controls.controller.AuxiliaryPersistenceWrapper
import com.android.systemui.controls.controller.ControlsFavoritePersistenceWrapper
@@ -59,6 +60,7 @@
"systemui.keyguard.quickaffordance.shared_preferences"
private const val COMMUNAL_PREFS_BACKUP_KEY =
"systemui.communal.shared_preferences"
+ private const val COMMUNAL_STATE_BACKUP_KEY = "systemui.communal_state"
val controlsDataLock = Any()
const val ACTION_RESTORE_FINISHED = "com.android.systemui.backup.RESTORE_FINISHED"
const val PERMISSION_SELF = "com.android.systemui.permission.SELF"
@@ -89,6 +91,10 @@
userId = userHandle.identifier,
)
)
+ addHelper(
+ COMMUNAL_STATE_BACKUP_KEY,
+ CommunalBackupHelper(userHandle, CommunalBackupUtils(context = this)),
+ )
}
}
@@ -116,7 +122,7 @@
}
private fun communalEnabled(): Boolean {
- return resources.getBoolean(R.bool.config_communalServiceEnabled) && communalHub()
+ return resources.getBoolean(R.bool.config_communalServiceEnabled)
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index d85b81d..ca88d40d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -71,7 +71,6 @@
import com.android.systemui.biometrics.domain.interactor.LogContextInteractor;
import com.android.systemui.biometrics.domain.interactor.PromptCredentialInteractor;
import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor;
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor;
import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams;
import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel;
import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel;
@@ -93,6 +92,9 @@
import kotlin.Unit;
+import kotlinx.coroutines.CoroutineScope;
+import kotlinx.coroutines.Job;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -106,9 +108,6 @@
import javax.inject.Inject;
import javax.inject.Provider;
-import kotlinx.coroutines.CoroutineScope;
-import kotlinx.coroutines.Job;
-
/**
* Receives messages sent from {@link com.android.server.biometrics.BiometricService} and shows the
* appropriate biometric UI (e.g. BiometricDialogView).
@@ -136,7 +135,6 @@
@Nullable private final FingerprintManager mFingerprintManager;
@Nullable private final FaceManager mFaceManager;
private final Provider<UdfpsController> mUdfpsControllerFactory;
- private final Provider<SideFpsController> mSidefpsControllerFactory;
private final CoroutineScope mApplicationCoroutineScope;
private Job mBiometricContextListenerJob = null;
@@ -163,7 +161,6 @@
@Nullable private UdfpsController mUdfpsController;
@Nullable private UdfpsOverlayParams mUdfpsOverlayParams;
@Nullable private IUdfpsRefreshRateRequestCallback mUdfpsRefreshRateRequestCallback;
- @Nullable private SideFpsController mSideFpsController;
@NonNull private Lazy<UdfpsLogger> mUdfpsLogger;
@VisibleForTesting IBiometricSysuiReceiver mReceiver;
@VisibleForTesting @NonNull final BiometricDisplayListener mOrientationListener;
@@ -320,14 +317,7 @@
this, mUdfpsLogger.get()));
mUdfpsBounds = mUdfpsProps.get(0).getLocation().getRect();
}
-
mSidefpsProps = !sidefpsProps.isEmpty() ? sidefpsProps : null;
- if (mSidefpsProps != null) {
- if (!SideFpsControllerRefactor.isEnabled()) {
- mSideFpsController = mSidefpsControllerFactory.get();
- }
- }
-
mFingerprintManager.registerBiometricStateListener(new BiometricStateListener() {
@Override
public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) {
@@ -738,7 +728,6 @@
@Nullable FingerprintManager fingerprintManager,
@Nullable FaceManager faceManager,
Provider<UdfpsController> udfpsControllerFactory,
- Provider<SideFpsController> sidefpsControllerFactory,
@NonNull DisplayManager displayManager,
@NonNull WakefulnessLifecycle wakefulnessLifecycle,
@NonNull AuthDialogPanelInteractionDetector panelInteractionDetector,
@@ -766,7 +755,6 @@
mFingerprintManager = fingerprintManager;
mFaceManager = faceManager;
mUdfpsControllerFactory = udfpsControllerFactory;
- mSidefpsControllerFactory = sidefpsControllerFactory;
mUdfpsLogger = udfpsLogger;
mDisplayManager = displayManager;
mWindowManager = windowManager;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
deleted file mode 100644
index 85f63e9..0000000
--- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * Copyright (C) 2021 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.biometrics
-
-import android.app.ActivityTaskManager
-import android.content.Context
-import android.content.res.Configuration
-import android.graphics.Color
-import android.graphics.PixelFormat
-import android.graphics.PorterDuff
-import android.graphics.PorterDuffColorFilter
-import android.graphics.Rect
-import android.hardware.biometrics.BiometricRequestConstants
-import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_KEYGUARD
-import android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_SETTINGS
-import android.hardware.biometrics.SensorLocationInternal
-import android.hardware.display.DisplayManager
-import android.hardware.fingerprint.FingerprintManager
-import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
-import android.hardware.fingerprint.ISidefpsController
-import android.os.Handler
-import android.util.Log
-import android.util.RotationUtils
-import android.view.Display
-import android.view.DisplayInfo
-import android.view.Gravity
-import android.view.LayoutInflater
-import android.view.Surface
-import android.view.View
-import android.view.View.AccessibilityDelegate
-import android.view.View.INVISIBLE
-import android.view.View.VISIBLE
-import android.view.ViewPropertyAnimator
-import android.view.WindowManager
-import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION
-import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
-import android.view.accessibility.AccessibilityEvent
-import androidx.annotation.RawRes
-import com.airbnb.lottie.LottieAnimationView
-import com.airbnb.lottie.LottieProperty
-import com.airbnb.lottie.model.KeyPath
-import com.android.app.animation.Interpolators
-import com.android.app.tracing.traceSection
-import com.android.internal.annotations.VisibleForTesting
-import com.android.keyguard.KeyguardPINView
-import com.android.systemui.Dumpable
-import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
-import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.res.R
-import com.android.systemui.util.boundsOnScreen
-import com.android.systemui.util.concurrency.DelayableExecutor
-import java.io.PrintWriter
-import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
-
-private const val TAG = "SideFpsController"
-
-/**
- * Shows and hides the side fingerprint sensor (side-fps) overlay and handles side fps touch events.
- */
-@SysUISingleton
-class SideFpsController
-@Inject
-constructor(
- private val context: Context,
- private val layoutInflater: LayoutInflater,
- fingerprintManager: FingerprintManager?,
- private val windowManager: WindowManager,
- private val activityTaskManager: ActivityTaskManager,
- displayManager: DisplayManager,
- private val displayStateInteractor: DisplayStateInteractor,
- @Main private val mainExecutor: DelayableExecutor,
- @Main private val handler: Handler,
- private val alternateBouncerInteractor: AlternateBouncerInteractor,
- @Application private val applicationScope: CoroutineScope,
- dumpManager: DumpManager,
- fpsUnlockTracker: FpsUnlockTracker
-) : Dumpable {
- private val requests: HashSet<SideFpsUiRequestSource> = HashSet()
-
- @VisibleForTesting
- val sensorProps: FingerprintSensorPropertiesInternal =
- fingerprintManager?.sideFpsSensorProperties
- ?: throw IllegalStateException("no side fingerprint sensor")
-
- @VisibleForTesting
- val orientationReasonListener =
- OrientationReasonListener(
- context,
- displayManager,
- handler,
- sensorProps,
- { reason -> onOrientationChanged(reason) },
- BiometricRequestConstants.REASON_UNKNOWN
- )
-
- @VisibleForTesting val orientationListener = orientationReasonListener.orientationListener
-
- private val isReverseDefaultRotation =
- context.resources.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)
-
- private var overlayShowAnimator: ViewPropertyAnimator? = null
-
- private var overlayView: View? = null
- set(value) {
- field?.let { oldView ->
- val lottie = oldView.requireViewById(R.id.sidefps_animation) as LottieAnimationView
- lottie.pauseAnimation()
- lottie.removeAllLottieOnCompositionLoadedListener()
- windowManager.removeView(oldView)
- orientationListener.disable()
- }
- overlayShowAnimator?.cancel()
- overlayShowAnimator = null
-
- field = value
- field?.let { newView ->
- if (requests.contains(SideFpsUiRequestSource.PRIMARY_BOUNCER)) {
- newView.alpha = 0f
- overlayShowAnimator =
- newView
- .animate()
- .alpha(1f)
- .setDuration(KeyguardPINView.ANIMATION_DURATION)
- .setInterpolator(Interpolators.ALPHA_IN)
- }
- windowManager.addView(newView, overlayViewParams)
- orientationListener.enable()
- overlayShowAnimator?.start()
- }
- }
- @VisibleForTesting var overlayOffsets: SensorLocationInternal = SensorLocationInternal.DEFAULT
-
- private val displayInfo = DisplayInfo()
-
- private val overlayViewParams =
- WindowManager.LayoutParams(
- WindowManager.LayoutParams.WRAP_CONTENT,
- WindowManager.LayoutParams.WRAP_CONTENT,
- WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
- Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS,
- PixelFormat.TRANSLUCENT
- )
- .apply {
- title = TAG
- fitInsetsTypes = 0 // overrides default, avoiding status bars during layout
- gravity = Gravity.TOP or Gravity.LEFT
- layoutInDisplayCutoutMode =
- WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
- privateFlags = PRIVATE_FLAG_TRUSTED_OVERLAY or PRIVATE_FLAG_NO_MOVE_ANIMATION
- }
-
- init {
- if (!SideFpsControllerRefactor.isEnabled) {
- fpsUnlockTracker.startTracking()
- fingerprintManager?.setSidefpsController(
- object : ISidefpsController.Stub() {
- override fun show(
- sensorId: Int,
- @BiometricRequestConstants.RequestReason reason: Int
- ) =
- if (reason.isReasonToAutoShow(activityTaskManager)) {
- show(SideFpsUiRequestSource.AUTO_SHOW, reason)
- } else {
- hide(SideFpsUiRequestSource.AUTO_SHOW)
- }
-
- override fun hide(sensorId: Int) = hide(SideFpsUiRequestSource.AUTO_SHOW)
- }
- )
- listenForAlternateBouncerVisibility()
-
- dumpManager.registerDumpable(this)
- }
- }
-
- private fun listenForAlternateBouncerVisibility() {
- if (!DeviceEntryUdfpsRefactor.isEnabled) {
- alternateBouncerInteractor.setAlternateBouncerUIAvailable(true, "SideFpsController")
- }
-
- applicationScope.launch {
- alternateBouncerInteractor.isVisible.collect { isVisible: Boolean ->
- if (isVisible) {
- show(SideFpsUiRequestSource.ALTERNATE_BOUNCER, REASON_AUTH_KEYGUARD)
- } else {
- hide(SideFpsUiRequestSource.ALTERNATE_BOUNCER)
- }
- }
- }
- }
-
- /** Shows the side fps overlay if not already shown. */
- fun show(
- request: SideFpsUiRequestSource,
- @BiometricRequestConstants.RequestReason
- reason: Int = BiometricRequestConstants.REASON_UNKNOWN
- ) {
- SideFpsControllerRefactor.assertInLegacyMode()
- if (!displayStateInteractor.isInRearDisplayMode.value) {
- requests.add(request)
- mainExecutor.execute {
- if (overlayView == null) {
- traceSection(
- "SideFpsController#show(request=${request.name}, reason=$reason)"
- ) {
- createOverlayForDisplay(reason)
- }
- } else {
- Log.v(TAG, "overlay already shown")
- }
- }
- }
- }
-
- /** Hides the fps overlay if shown. */
- fun hide(request: SideFpsUiRequestSource) {
- SideFpsControllerRefactor.assertInLegacyMode()
- requests.remove(request)
- mainExecutor.execute {
- if (requests.isEmpty()) {
- traceSection("SideFpsController#hide(${request.name})") { overlayView = null }
- }
- }
- }
-
- /** Hide the arrow indicator. */
- fun hideIndicator() {
- SideFpsControllerRefactor.assertInLegacyMode()
- val lottieAnimationView =
- overlayView?.findViewById(R.id.sidefps_animation) as LottieAnimationView?
- lottieAnimationView?.visibility = INVISIBLE
- }
-
- /** Show the arrow indicator. */
- fun showIndicator() {
- SideFpsControllerRefactor.assertInLegacyMode()
- val lottieAnimationView =
- overlayView?.findViewById(R.id.sidefps_animation) as LottieAnimationView?
- lottieAnimationView?.visibility = VISIBLE
- }
-
- override fun dump(pw: PrintWriter, args: Array<out String>) {
- pw.println("requests:")
- for (requestSource in requests) {
- pw.println(" $requestSource.name")
- }
-
- pw.println("overlayView:")
- pw.println(" width=${overlayView?.width}")
- pw.println(" height=${overlayView?.height}")
- pw.println(" boundsOnScreen=${overlayView?.boundsOnScreen}")
-
- pw.println("displayStateInteractor:")
- pw.println(" isInRearDisplayMode=${displayStateInteractor?.isInRearDisplayMode?.value}")
-
- pw.println("sensorProps:")
- pw.println(" displayId=${displayInfo.uniqueId}")
- pw.println(" sensorType=${sensorProps?.sensorType}")
- pw.println(" location=${sensorProps?.getLocation(displayInfo.uniqueId)}")
- pw.println("lottieAnimationView:")
- pw.println(
- " visibility=${overlayView?.findViewById<View>(R.id.sidefps_animation)?.visibility}"
- )
-
- pw.println("overlayOffsets=$overlayOffsets")
- pw.println("isReverseDefaultRotation=$isReverseDefaultRotation")
- pw.println("currentRotation=${displayInfo.rotation}")
- }
-
- private fun onOrientationChanged(@BiometricRequestConstants.RequestReason reason: Int) {
- if (overlayView?.isAttachedToWindow == true) {
- createOverlayForDisplay(reason)
- }
- }
-
- private fun createOverlayForDisplay(@BiometricRequestConstants.RequestReason reason: Int) {
- val view = layoutInflater.inflate(R.layout.sidefps_view, null, false)
- overlayView = view
- val display = context.display!!
- // b/284098873 `context.display.rotation` may not up-to-date, we use displayInfo.rotation
- display.getDisplayInfo(displayInfo)
- val offsets =
- sensorProps.getLocation(display.uniqueId).let { location ->
- if (location == null) {
- Log.w(TAG, "No location specified for display: ${display.uniqueId}")
- }
- location ?: sensorProps.location
- }
- overlayOffsets = offsets
-
- val lottie = view.requireViewById(R.id.sidefps_animation) as LottieAnimationView
- view.rotation =
- display.asSideFpsAnimationRotation(
- offsets.isYAligned(),
- getRotationFromDefault(displayInfo.rotation)
- )
- lottie.setAnimation(
- display.asSideFpsAnimation(
- offsets.isYAligned(),
- getRotationFromDefault(displayInfo.rotation)
- )
- )
- lottie.addLottieOnCompositionLoadedListener {
- // Check that view is not stale, and that overlayView has not been hidden/removed
- if (overlayView?.isAttachedToWindow == true && overlayView == view) {
- updateOverlayParams(display, it.bounds)
- }
- }
- orientationReasonListener.reason = reason
- lottie.addOverlayDynamicColor(context, reason)
-
- /**
- * Intercepts TYPE_WINDOW_STATE_CHANGED accessibility event, preventing Talkback from
- * speaking @string/accessibility_fingerprint_label twice when sensor location indicator is
- * in focus
- */
- view.setAccessibilityDelegate(
- object : AccessibilityDelegate() {
- override fun dispatchPopulateAccessibilityEvent(
- host: View,
- event: AccessibilityEvent
- ): Boolean {
- return if (
- event.getEventType() === AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
- ) {
- true
- } else {
- super.dispatchPopulateAccessibilityEvent(host, event)
- }
- }
- }
- )
- }
-
- @VisibleForTesting
- fun updateOverlayParams(display: Display, bounds: Rect) {
- val isNaturalOrientation = display.isNaturalOrientation()
- val isDefaultOrientation =
- if (isReverseDefaultRotation) !isNaturalOrientation else isNaturalOrientation
- val size = windowManager.maximumWindowMetrics.bounds
-
- val displayWidth = if (isDefaultOrientation) size.width() else size.height()
- val displayHeight = if (isDefaultOrientation) size.height() else size.width()
- val boundsWidth = if (isDefaultOrientation) bounds.width() else bounds.height()
- val boundsHeight = if (isDefaultOrientation) bounds.height() else bounds.width()
-
- val sensorBounds =
- if (overlayOffsets.isYAligned()) {
- Rect(
- displayWidth - boundsWidth,
- overlayOffsets.sensorLocationY,
- displayWidth,
- overlayOffsets.sensorLocationY + boundsHeight
- )
- } else {
- Rect(
- overlayOffsets.sensorLocationX,
- 0,
- overlayOffsets.sensorLocationX + boundsWidth,
- boundsHeight
- )
- }
-
- RotationUtils.rotateBounds(
- sensorBounds,
- Rect(0, 0, displayWidth, displayHeight),
- getRotationFromDefault(display.rotation)
- )
-
- overlayViewParams.x = sensorBounds.left
- overlayViewParams.y = sensorBounds.top
-
- windowManager.updateViewLayout(overlayView, overlayViewParams)
- }
-
- private fun getRotationFromDefault(rotation: Int): Int =
- if (isReverseDefaultRotation) (rotation + 1) % 4 else rotation
-}
-
-private val FingerprintManager?.sideFpsSensorProperties: FingerprintSensorPropertiesInternal?
- get() = this?.sensorPropertiesInternal?.firstOrNull { it.isAnySidefpsType }
-
-/** Returns [True] when the device has a side fingerprint sensor. */
-fun FingerprintManager?.hasSideFpsSensor(): Boolean = this?.sideFpsSensorProperties != null
-
-@BiometricRequestConstants.RequestReason
-private fun Int.isReasonToAutoShow(activityTaskManager: ActivityTaskManager): Boolean =
- when (this) {
- REASON_AUTH_KEYGUARD -> false
- REASON_AUTH_SETTINGS ->
- when (activityTaskManager.topClass()) {
- // TODO(b/186176653): exclude fingerprint overlays from this list view
- "com.android.settings.biometrics.fingerprint.FingerprintSettings" -> false
- else -> true
- }
- else -> true
- }
-
-private fun ActivityTaskManager.topClass(): String =
- getTasks(1).firstOrNull()?.topActivity?.className ?: ""
-
-@RawRes
-private fun Display.asSideFpsAnimation(yAligned: Boolean, rotationFromDefault: Int): Int =
- when (rotationFromDefault) {
- Surface.ROTATION_0 -> if (yAligned) R.raw.sfps_pulse else R.raw.sfps_pulse_landscape
- Surface.ROTATION_180 -> if (yAligned) R.raw.sfps_pulse else R.raw.sfps_pulse_landscape
- else -> if (yAligned) R.raw.sfps_pulse_landscape else R.raw.sfps_pulse
- }
-
-private fun Display.asSideFpsAnimationRotation(yAligned: Boolean, rotationFromDefault: Int): Float =
- when (rotationFromDefault) {
- Surface.ROTATION_90 -> if (yAligned) 0f else 180f
- Surface.ROTATION_180 -> 180f
- Surface.ROTATION_270 -> if (yAligned) 180f else 0f
- else -> 0f
- }
-
-private fun SensorLocationInternal.isYAligned(): Boolean = sensorLocationY != 0
-
-private fun Display.isNaturalOrientation(): Boolean =
- rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180
-
-private fun LottieAnimationView.addOverlayDynamicColor(
- context: Context,
- @BiometricRequestConstants.RequestReason reason: Int
-) {
- fun update() {
- val isKeyguard = reason == REASON_AUTH_KEYGUARD
- if (isKeyguard) {
- val color =
- com.android.settingslib.Utils.getColorAttrDefaultColor(
- context,
- com.android.internal.R.attr.materialColorPrimaryFixed
- )
- val outerRimColor =
- com.android.settingslib.Utils.getColorAttrDefaultColor(
- context,
- com.android.internal.R.attr.materialColorPrimaryFixedDim
- )
- val chevronFill =
- com.android.settingslib.Utils.getColorAttrDefaultColor(
- context,
- com.android.internal.R.attr.materialColorOnPrimaryFixed
- )
- addValueCallback(KeyPath(".blue600", "**"), LottieProperty.COLOR_FILTER) {
- PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP)
- }
- addValueCallback(KeyPath(".blue400", "**"), LottieProperty.COLOR_FILTER) {
- PorterDuffColorFilter(outerRimColor, PorterDuff.Mode.SRC_ATOP)
- }
- addValueCallback(KeyPath(".black", "**"), LottieProperty.COLOR_FILTER) {
- PorterDuffColorFilter(chevronFill, PorterDuff.Mode.SRC_ATOP)
- }
- } else {
- if (!isDarkMode(context)) {
- addValueCallback(KeyPath(".black", "**"), LottieProperty.COLOR_FILTER) {
- PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP)
- }
- }
- for (key in listOf(".blue600", ".blue400")) {
- addValueCallback(KeyPath(key, "**"), LottieProperty.COLOR_FILTER) {
- PorterDuffColorFilter(
- context.getColor(
- com.android.settingslib.color.R.color.settingslib_color_blue400
- ),
- PorterDuff.Mode.SRC_ATOP
- )
- }
- }
- }
- }
-
- if (composition != null) {
- update()
- } else {
- addLottieOnCompositionLoadedListener { update() }
- }
-}
-
-private fun isDarkMode(context: Context): Boolean {
- val darkMode = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
- return darkMode == Configuration.UI_MODE_NIGHT_YES
-}
-
-@VisibleForTesting
-class OrientationReasonListener(
- context: Context,
- displayManager: DisplayManager,
- handler: Handler,
- sensorProps: FingerprintSensorPropertiesInternal,
- onOrientationChanged: (reason: Int) -> Unit,
- @BiometricRequestConstants.RequestReason var reason: Int
-) {
- val orientationListener =
- BiometricDisplayListener(
- context,
- displayManager,
- handler,
- BiometricDisplayListener.SensorType.SideFingerprint(sensorProps)
- ) {
- onOrientationChanged(reason)
- }
-}
-
-/**
- * The source of a request to show the side fps visual indicator. This is distinct from
- * [BiometricRequestConstants] which corresponds with the reason fingerprint authentication is
- * requested.
- */
-enum class SideFpsUiRequestSource {
- /** see [isReasonToAutoShow] */
- AUTO_SHOW,
- /** Pin, pattern or password bouncer */
- PRIMARY_BOUNCER,
- ALTERNATE_BOUNCER,
-}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt
index 59b59bf..7d4ba84 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt
@@ -39,6 +39,7 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.keyguard.shared.model.DevicePosture
import com.android.systemui.res.R
import java.util.concurrent.Executor
import javax.inject.Inject
@@ -68,6 +69,8 @@
/** The info of current available camera. */
val cameraInfo: StateFlow<CameraInfo?>
+
+ val supportedPostures: List<DevicePosture>
}
/** Describes a biometric sensor */
@@ -188,6 +191,15 @@
initialValue = if (cameraInfoList.isNotEmpty()) cameraInfoList[0] else null
)
+ private val supportedPosture =
+ applicationContext.resources.getInteger(R.integer.config_face_auth_supported_posture)
+ override val supportedPostures: List<DevicePosture> =
+ if (supportedPosture == 0) {
+ DevicePosture.entries
+ } else {
+ listOf(DevicePosture.toPosture(supportedPosture))
+ }
+
private val defaultSensorLocation: StateFlow<Point?> =
cameraInfo
.map { it?.cameraLocation }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/shared/SideFpsControllerRefactor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/shared/SideFpsControllerRefactor.kt
deleted file mode 100644
index 899b07e..0000000
--- a/packages/SystemUI/src/com/android/systemui/biometrics/shared/SideFpsControllerRefactor.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2023 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.biometrics.shared
-
-import com.android.systemui.flags.FlagToken
-import com.android.systemui.flags.RefactorFlagUtils
-import com.android.systemui.shared.Flags
-
-/** Helper for reading or using the sidefps controller refactor flag state. */
-@Suppress("NOTHING_TO_INLINE")
-object SideFpsControllerRefactor {
- /** The aconfig flag name */
- const val FLAG_NAME = Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
-
- /** A token used for dependency declaration */
- val token: FlagToken
- get() = FlagToken(FLAG_NAME, isEnabled)
-
- /** Is the refactor enabled */
- @JvmStatic
- inline val isEnabled
- get() = Flags.sidefpsControllerRefactor()
-
- /**
- * Called to ensure code is only run when the flag is enabled. This protects users from the
- * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
- * build to ensure that the refactor author catches issues in testing.
- */
- @JvmStatic
- inline fun isUnexpectedlyInLegacyMode() =
- RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
-
- /**
- * Called to ensure code is only run when the flag is disabled. This will throw an exception if
- * the flag is enabled to ensure that the refactor author catches issues in testing.
- */
- @JvmStatic
- inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
-}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
index 9949e4c..245817e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinder.kt
@@ -36,7 +36,6 @@
import com.android.systemui.biometrics.domain.interactor.BiometricStatusInteractor
import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
import com.android.systemui.biometrics.domain.interactor.SideFpsSensorInteractor
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
import com.android.systemui.biometrics.shared.model.AuthenticationReason.NotRunning
import com.android.systemui.biometrics.shared.model.LottieCallback
import com.android.systemui.biometrics.ui.viewmodel.SideFpsOverlayViewModel
@@ -73,10 +72,6 @@
) : CoreStartable {
override fun start() {
- if (!SideFpsControllerRefactor.isEnabled) {
- return
- }
-
applicationScope
.launch {
sfpsSensorInteractor.get().isAvailable.collect { isSfpsAvailable ->
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt
index d0ff185..346ea54 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/data/repository/KeyguardBouncerRepository.kt
@@ -18,7 +18,6 @@
import android.os.Build
import android.util.Log
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
import com.android.systemui.bouncer.shared.model.BouncerDismissActionModel
import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
@@ -89,7 +88,6 @@
val resourceUpdateRequests: StateFlow<Boolean>
val alternateBouncerVisible: StateFlow<Boolean>
val alternateBouncerUIAvailable: StateFlow<Boolean>
- val sideFpsShowing: StateFlow<Boolean>
/** Action that should be run right after the bouncer is dismissed. */
var bouncerDismissActionModel: BouncerDismissActionModel?
@@ -125,9 +123,6 @@
fun setAlternateVisible(isVisible: Boolean)
fun setAlternateBouncerUIAvailable(isAvailable: Boolean)
-
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- fun setSideFpsShowing(isShowing: Boolean)
}
@SysUISingleton
@@ -196,8 +191,6 @@
private val _alternateBouncerUIAvailable = MutableStateFlow(false)
override val alternateBouncerUIAvailable: StateFlow<Boolean> =
_alternateBouncerUIAvailable.asStateFlow()
- private val _sideFpsShowing = MutableStateFlow(false)
- override val sideFpsShowing: StateFlow<Boolean> = _sideFpsShowing.asStateFlow()
init {
setUpLogging()
@@ -269,12 +262,6 @@
_isBackButtonEnabled.value = isBackButtonEnabled
}
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- override fun setSideFpsShowing(isShowing: Boolean) {
- SideFpsControllerRefactor.assertInLegacyMode()
- _sideFpsShowing.value = isShowing
- }
-
/** Sets up logs for state flows. */
private fun setUpLogging() {
if (!Build.IS_DEBUGGABLE) {
@@ -321,9 +308,6 @@
alternateBouncerUIAvailable
.logDiffsForTable(buffer, "", "IsAlternateBouncerUIAvailable", false)
.launchIn(applicationScope)
- sideFpsShowing
- .logDiffsForTable(buffer, "", "isSideFpsShowing", false)
- .launchIn(applicationScope)
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt
index d88b3dc..a91635b 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/PrimaryBouncerInteractor.kt
@@ -18,18 +18,14 @@
import android.content.Context
import android.content.res.ColorStateList
-import android.hardware.biometrics.BiometricSourceType
import android.os.Handler
import android.os.Trace
import android.util.Log
import android.view.View
-import com.android.keyguard.KeyguardConstants
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.DejankUtils
import com.android.systemui.Flags
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN
@@ -122,31 +118,9 @@
/** Allow for interaction when just about fully visible */
val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 }
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- val sideFpsShowing: Flow<Boolean> = repository.sideFpsShowing
private var currentUserActiveUnlockRunning = false
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- /** This callback needs to be a class field so it does not get garbage collected. */
- val keyguardUpdateMonitorCallback =
- object : KeyguardUpdateMonitorCallback() {
- override fun onBiometricRunningStateChanged(
- running: Boolean,
- biometricSourceType: BiometricSourceType?
- ) {
- updateSideFpsVisibility()
- }
-
- override fun onStrongAuthStateChanged(userId: Int) {
- updateSideFpsVisibility()
- }
- }
-
init {
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- if (!SideFpsControllerRefactor.isEnabled) {
- keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
- }
applicationScope.launch {
trustRepository.isCurrentUserActiveUnlockRunning.collect {
currentUserActiveUnlockRunning = it
@@ -357,36 +331,6 @@
repository.setPrimaryStartDisappearAnimation(runnable)
}
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- /** Determine whether to show the side fps animation. */
- fun updateSideFpsVisibility() {
- SideFpsControllerRefactor.assertInLegacyMode()
- val sfpsEnabled: Boolean =
- context.resources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer)
- val fpsDetectionRunning: Boolean = keyguardUpdateMonitor.isFingerprintDetectionRunning
- val isUnlockingWithFpAllowed: Boolean =
- keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed
- val toShow =
- (isBouncerShowing() &&
- sfpsEnabled &&
- fpsDetectionRunning &&
- isUnlockingWithFpAllowed &&
- !isAnimatingAway())
-
- if (KeyguardConstants.DEBUG) {
- Log.d(
- TAG,
- ("sideFpsToShow=$toShow\n" +
- "isBouncerShowing=${isBouncerShowing()}\n" +
- "configEnabled=$sfpsEnabled\n" +
- "fpsDetectionRunning=$fpsDetectionRunning\n" +
- "isUnlockingWithFpAllowed=$isUnlockingWithFpAllowed\n" +
- "isAnimatingAway=${isAnimatingAway()}")
- )
- }
- repository.setSideFpsShowing(toShow)
- }
-
/** Returns whether bouncer is fully showing. */
fun isFullyShowing(): Boolean {
return (repository.primaryBouncerShowingSoon.value || isBouncerShowing()) &&
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt
index cc387e9..b76520b 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/KeyguardBouncerViewBinder.kt
@@ -27,7 +27,6 @@
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardSecurityView
import com.android.keyguard.dagger.KeyguardBouncerComponent
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
import com.android.systemui.bouncer.ui.BouncerViewDelegate
@@ -231,23 +230,6 @@
.collect { view.systemUiVisibility = it }
}
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- if (!SideFpsControllerRefactor.isEnabled) {
- launch {
- viewModel.shouldUpdateSideFps.collect {
- viewModel.updateSideFpsVisibility()
- }
- }
- }
-
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- if (!SideFpsControllerRefactor.isEnabled) {
- launch {
- viewModel.sideFpsShowing.collect {
- securityContainerController.updateSideFpsVisibility(it)
- }
- }
- }
awaitCancellation()
} finally {
viewModel.setBouncerViewDelegate(null)
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt
index e1fea5f..3fef766 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/KeyguardBouncerViewModel.kt
@@ -17,7 +17,6 @@
package com.android.systemui.bouncer.ui.viewmodel
import android.view.View
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
import com.android.systemui.bouncer.ui.BouncerView
@@ -25,9 +24,7 @@
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.merge
/** Models UI state for the lock screen bouncer; handles user input. */
@ExperimentalCoroutinesApi
@@ -64,19 +61,6 @@
/** Observe whether keyguard is authenticated already. */
val keyguardAuthenticated: Flow<Boolean> = interactor.keyguardAuthenticatedBiometrics
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- /** Observe whether the side fps is showing. */
- val sideFpsShowing: Flow<Boolean> = interactor.sideFpsShowing
-
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- /** Observe whether we should update fps is showing. */
- val shouldUpdateSideFps: Flow<Unit> =
- merge(
- interactor.isShowing.map {},
- interactor.startingToHide,
- interactor.startingDisappearAnimation.filterNotNull().map {}
- )
-
/** Observe whether we want to update resources. */
fun notifyUpdateResources() {
interactor.notifyUpdatedResources()
@@ -92,12 +76,6 @@
interactor.onMessageShown()
}
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- fun updateSideFpsVisibility() {
- SideFpsControllerRefactor.assertInLegacyMode()
- interactor.updateSideFpsVisibility()
- }
-
/** Observe whether back button is enabled. */
fun observeOnIsBackButtonEnabled(systemUiVisibility: () -> Int): Flow<Int> {
return interactor.isBackButtonEnabled.map { enabled ->
diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalBackupRestoreStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalBackupRestoreStartable.kt
new file mode 100644
index 0000000..cdeeb6f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalBackupRestoreStartable.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2024 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.communal
+
+import android.appwidget.AppWidgetManager
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import com.android.systemui.CoreStartable
+import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.communal.domain.interactor.CommunalInteractor
+import com.android.systemui.communal.widgets.CommunalWidgetModule
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.core.Logger
+import com.android.systemui.log.dagger.CommunalLog
+import javax.inject.Inject
+
+@SysUISingleton
+class CommunalBackupRestoreStartable
+@Inject
+constructor(
+ private val broadcastDispatcher: BroadcastDispatcher,
+ private val communalInteractor: CommunalInteractor,
+ @CommunalLog logBuffer: LogBuffer,
+) : CoreStartable, BroadcastReceiver() {
+
+ private val logger = Logger(logBuffer, TAG)
+
+ override fun start() {
+ broadcastDispatcher.registerReceiver(
+ receiver = this,
+ filter = IntentFilter(AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED),
+ )
+ }
+
+ override fun onReceive(context: Context?, intent: Intent?) {
+ if (intent == null) {
+ logger.w("On app widget host restored, but intent is null")
+ return
+ }
+
+ if (intent.action != AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED) {
+ return
+ }
+
+ val hostId = intent.getIntExtra(AppWidgetManager.EXTRA_HOST_ID, 0)
+ if (hostId != CommunalWidgetModule.APP_WIDGET_HOST_ID) {
+ return
+ }
+
+ val oldIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_OLD_IDS)
+ val newIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS)
+
+ if (oldIds == null || newIds == null || oldIds.size != newIds.size) {
+ logger.w("On app widget host restored, but old to new ids mapping is invalid")
+ communalInteractor.abortRestoreWidgets()
+ return
+ }
+
+ val oldToNewWidgetIdMap = oldIds.zip(newIds).toMap()
+ communalInteractor.restoreWidgets(oldToNewWidgetIdMap)
+ }
+
+ companion object {
+ const val TAG = "CommunalBackupRestoreStartable"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt
index 5a174b9..f437032 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt
@@ -17,6 +17,7 @@
package com.android.systemui.communal
import android.provider.Settings
+import android.service.dreams.Flags.dreamTracksFocus
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.CoreStartable
import com.android.systemui.communal.domain.interactor.CommunalInteractor
@@ -25,11 +26,13 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dock.DockManager
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.util.kotlin.emitOnStart
import com.android.systemui.util.kotlin.sample
import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
@@ -37,15 +40,18 @@
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
+import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
/**
* A [CoreStartable] responsible for automatically navigating between communal scenes when certain
@@ -61,8 +67,10 @@
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
private val keyguardInteractor: KeyguardInteractor,
private val systemSettings: SystemSettings,
+ private val notificationShadeWindowController: NotificationShadeWindowController,
@Application private val applicationScope: CoroutineScope,
@Background private val bgScope: CoroutineScope,
+ @Main private val mainDispatcher: CoroutineDispatcher,
) : CoreStartable {
private var screenTimeout: Int = DEFAULT_SCREEN_TIMEOUT
@@ -134,6 +142,16 @@
}
}
}
+
+ if (dreamTracksFocus()) {
+ bgScope.launch {
+ communalInteractor.isIdleOnCommunal.collectLatest {
+ withContext(mainDispatcher) {
+ notificationShadeWindowController.setGlanceableHubShowing(it)
+ }
+ }
+ }
+ }
}
private suspend fun determineSceneAfterTransition(
diff --git a/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.kt b/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.kt
index 27af99e..7fa091a 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/dagger/CommunalModule.kt
@@ -16,6 +16,8 @@
package com.android.systemui.communal.dagger
+import android.content.Context
+import com.android.systemui.communal.data.backup.CommunalBackupUtils
import com.android.systemui.communal.data.db.CommunalDatabaseModule
import com.android.systemui.communal.data.repository.CommunalMediaRepositoryModule
import com.android.systemui.communal.data.repository.CommunalPrefsRepositoryModule
@@ -78,5 +80,13 @@
)
return SceneDataSourceDelegator(applicationScope, config)
}
+
+ @Provides
+ @SysUISingleton
+ fun providesCommunalBackupUtils(
+ @Application context: Context,
+ ): CommunalBackupUtils {
+ return CommunalBackupUtils(context)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupHelper.kt b/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupHelper.kt
new file mode 100644
index 0000000..b95c966
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupHelper.kt
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2024 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.communal.data.backup
+
+import android.app.backup.BackupDataInputStream
+import android.app.backup.BackupDataOutput
+import android.app.backup.BackupHelper
+import android.os.ParcelFileDescriptor
+import android.os.UserHandle
+import android.util.Log
+import com.android.systemui.Flags.communalHub
+import com.android.systemui.communal.proto.toByteArray
+import java.io.IOException
+
+/** Helps with backup & restore of the communal hub widgets. */
+class CommunalBackupHelper(
+ private val userHandle: UserHandle,
+ private val communalBackupUtils: CommunalBackupUtils,
+) : BackupHelper {
+
+ override fun performBackup(
+ oldState: ParcelFileDescriptor?,
+ data: BackupDataOutput?,
+ newState: ParcelFileDescriptor?
+ ) {
+ if (!communalHub()) {
+ Log.d(TAG, "Skipping backup. Communal not enabled")
+ return
+ }
+
+ if (data == null) {
+ Log.e(TAG, "Backup failed. Data is null")
+ return
+ }
+
+ if (!userHandle.isSystem) {
+ Log.d(TAG, "Backup skipped for non-system user")
+ return
+ }
+
+ val state = communalBackupUtils.getCommunalHubState()
+ Log.i(TAG, "Backing up communal state: $state")
+
+ val bytes = state.toByteArray()
+ try {
+ data.writeEntityHeader(ENTITY_KEY, bytes.size)
+ data.writeEntityData(bytes, bytes.size)
+ } catch (e: IOException) {
+ Log.e(TAG, "Backup failed while writing data: ${e.localizedMessage}")
+ return
+ }
+
+ Log.i(TAG, "Backup complete")
+ }
+
+ override fun restoreEntity(data: BackupDataInputStream?) {
+ if (data == null) {
+ Log.e(TAG, "Restore failed. Data is null")
+ return
+ }
+
+ if (!userHandle.isSystem) {
+ Log.d(TAG, "Restore skipped for non-system user")
+ return
+ }
+
+ if (data.key != ENTITY_KEY) {
+ Log.d(TAG, "Restore skipped due to mismatching entity key")
+ return
+ }
+
+ val dataSize = data.size()
+ val bytes = ByteArray(dataSize)
+ try {
+ data.read(bytes, /* offset= */ 0, dataSize)
+ } catch (e: IOException) {
+ Log.e(TAG, "Restore failed while reading data: ${e.localizedMessage}")
+ return
+ }
+
+ try {
+ communalBackupUtils.writeBytesToDisk(bytes)
+ } catch (e: Exception) {
+ Log.e(TAG, "Restore failed while writing to disk: ${e.localizedMessage}")
+ return
+ }
+
+ Log.i(TAG, "Restore complete")
+ }
+
+ override fun writeNewStateDescription(newState: ParcelFileDescriptor?) {
+ // Do nothing because there is no partial backup
+ }
+
+ companion object {
+ private const val TAG = "CommunalBackupHelper"
+
+ const val ENTITY_KEY = "communal_hub_state"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupUtils.kt b/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupUtils.kt
new file mode 100644
index 0000000..a8e5174
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/backup/CommunalBackupUtils.kt
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2024 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.communal.data.backup
+
+import android.content.Context
+import androidx.annotation.WorkerThread
+import com.android.systemui.communal.data.db.CommunalDatabase
+import com.android.systemui.communal.nano.CommunalHubState
+import java.io.File
+import java.io.FileInputStream
+import java.io.FileNotFoundException
+import java.io.FileOutputStream
+import java.io.IOException
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.runBlocking
+
+/** Utilities for communal backup and restore. */
+class CommunalBackupUtils(
+ private val context: Context,
+) {
+
+ /**
+ * Retrieves a communal hub state protobuf that represents the current state of the communal
+ * database.
+ */
+ @WorkerThread
+ fun getCommunalHubState(): CommunalHubState {
+ val database = CommunalDatabase.getInstance(context)
+ val widgetsFromDb = runBlocking { database.communalWidgetDao().getWidgets().first() }
+ val widgetsState = mutableListOf<CommunalHubState.CommunalWidgetItem>()
+ widgetsFromDb.keys.forEach { rankItem ->
+ widgetsState.add(
+ CommunalHubState.CommunalWidgetItem().apply {
+ rank = rankItem.rank
+ widgetId = widgetsFromDb[rankItem]!!.widgetId
+ componentName = widgetsFromDb[rankItem]?.componentName
+ }
+ )
+ }
+ return CommunalHubState().apply { widgets = widgetsState.toTypedArray() }
+ }
+
+ /**
+ * Writes [data] to disk as a file as [FILE_NAME], overwriting existing content if any.
+ *
+ * @throws FileNotFoundException if the file exists but is a directory rather than a regular
+ * file, does not exist but cannot be created, or cannot be opened for any other reason.
+ * @throws SecurityException if write access is denied.
+ * @throws IOException if writing fails.
+ */
+ @WorkerThread
+ fun writeBytesToDisk(data: ByteArray) {
+ val output = FileOutputStream(getFile())
+ output.write(data)
+ output.close()
+ }
+
+ /**
+ * Reads bytes from [FILE_NAME], and throws if file does not exist.
+ *
+ * @throws FileNotFoundException if file does not exist.
+ * @throws SecurityException if read access is denied.
+ * @throws IOException if reading fails.
+ */
+ @WorkerThread
+ fun readBytesFromDisk(): ByteArray {
+ val input = FileInputStream(getFile())
+ val bytes = input.readAllBytes()
+ input.close()
+
+ return bytes
+ }
+
+ /**
+ * Removes the bytes written to disk at [FILE_NAME].
+ *
+ * @return True if and only if the file is successfully deleted
+ * @throws SecurityException if permission is denied
+ */
+ @WorkerThread
+ fun clear(): Boolean {
+ return getFile().delete()
+ }
+
+ /** Whether [FILE_NAME] exists. */
+ @WorkerThread
+ fun fileExists(): Boolean {
+ return getFile().exists()
+ }
+
+ @WorkerThread
+ private fun getFile(): File {
+ return File(context.filesDir, FILE_NAME)
+ }
+
+ companion object {
+ private const val FILE_NAME = "communal_restore"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabase.kt b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabase.kt
index 595d320..3ce8109 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabase.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabase.kt
@@ -16,10 +16,53 @@
package com.android.systemui.communal.data.db
+import android.content.Context
+import androidx.annotation.VisibleForTesting
import androidx.room.Database
+import androidx.room.Room
import androidx.room.RoomDatabase
+import com.android.systemui.res.R
@Database(entities = [CommunalWidgetItem::class, CommunalItemRank::class], version = 1)
abstract class CommunalDatabase : RoomDatabase() {
abstract fun communalWidgetDao(): CommunalWidgetDao
+
+ companion object {
+ private var instance: CommunalDatabase? = null
+
+ /**
+ * Gets a singleton instance of the communal database. If this is called for the first time
+ * globally, a new instance is created.
+ *
+ * @param context The context the database is created in. Only effective when a new instance
+ * is created.
+ * @param callback An optional callback registered to the database. Only effective when a
+ * new instance is created.
+ */
+ fun getInstance(
+ context: Context,
+ callback: Callback? = null,
+ ): CommunalDatabase {
+ if (instance == null) {
+ instance =
+ Room.databaseBuilder(
+ context,
+ CommunalDatabase::class.java,
+ context.resources.getString(R.string.config_communalDatabase)
+ )
+ .also { builder ->
+ builder.fallbackToDestructiveMigration(dropAllTables = false)
+ callback?.let { callback -> builder.addCallback(callback) }
+ }
+ .build()
+ }
+
+ return instance!!
+ }
+
+ @VisibleForTesting
+ fun setInstance(database: CommunalDatabase) {
+ instance = database
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabaseModule.kt b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabaseModule.kt
index e766290..b8161fd 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabaseModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalDatabaseModule.kt
@@ -17,10 +17,8 @@
package com.android.systemui.communal.data.db
import android.content.Context
-import androidx.room.Room
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.res.R
import dagger.Module
import dagger.Provides
@@ -33,14 +31,7 @@
@Application context: Context,
defaultWidgetPopulation: DefaultWidgetPopulation,
): CommunalDatabase {
- return Room.databaseBuilder(
- context,
- CommunalDatabase::class.java,
- context.resources.getString(R.string.config_communalDatabase)
- )
- .fallbackToDestructiveMigration()
- .addCallback(defaultWidgetPopulation)
- .build()
+ return CommunalDatabase.getInstance(context, defaultWidgetPopulation)
}
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt
index 9cd77c4..d174fd1 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/db/CommunalWidgetDao.kt
@@ -23,6 +23,7 @@
import androidx.room.RoomDatabase
import androidx.room.Transaction
import androidx.sqlite.db.SupportSQLiteDatabase
+import com.android.systemui.communal.nano.CommunalHubState
import com.android.systemui.communal.widgets.CommunalWidgetHost
import com.android.systemui.communal.widgets.CommunalWidgetModule.Companion.DEFAULT_WIDGETS
import com.android.systemui.dagger.qualifiers.Application
@@ -116,6 +117,10 @@
@Query("UPDATE communal_item_rank_table SET rank = :order WHERE uid = :itemUid")
fun updateItemRank(itemUid: Long, order: Int)
+ @Query("DELETE FROM communal_widget_table") fun clearCommunalWidgetsTable()
+
+ @Query("DELETE FROM communal_item_rank_table") fun clearCommunalItemRankTable()
+
@Transaction
fun updateWidgetOrder(widgetIdToPriorityMap: Map<Int, Int>) {
widgetIdToPriorityMap.forEach { (id, priority) ->
@@ -128,9 +133,18 @@
@Transaction
fun addWidget(widgetId: Int, provider: ComponentName, priority: Int): Long {
- return insertWidget(
+ return addWidget(
widgetId = widgetId,
componentName = provider.flattenToString(),
+ priority = priority,
+ )
+ }
+
+ @Transaction
+ fun addWidget(widgetId: Int, componentName: String, priority: Int): Long {
+ return insertWidget(
+ widgetId = widgetId,
+ componentName = componentName,
itemId = insertItemRank(priority),
)
}
@@ -145,4 +159,13 @@
deleteWidgets(widget)
return true
}
+
+ /** Wipes current database and restores the snapshot represented by [state]. */
+ @Transaction
+ fun restoreCommunalHubState(state: CommunalHubState) {
+ clearCommunalWidgetsTable()
+ clearCommunalItemRankTable()
+
+ state.widgets.forEach { addWidget(it.widgetId, it.componentName, it.rank) }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt
index e395ca9..1f54e70 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/data/repository/CommunalWidgetRepository.kt
@@ -16,13 +16,17 @@
package com.android.systemui.communal.data.repository
+import android.app.backup.BackupManager
import android.appwidget.AppWidgetManager
import android.content.ComponentName
import android.os.UserHandle
import androidx.annotation.WorkerThread
+import com.android.systemui.communal.data.backup.CommunalBackupUtils
import com.android.systemui.communal.data.db.CommunalItemRank
import com.android.systemui.communal.data.db.CommunalWidgetDao
import com.android.systemui.communal.data.db.CommunalWidgetItem
+import com.android.systemui.communal.nano.CommunalHubState
+import com.android.systemui.communal.proto.toCommunalHubState
import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
import com.android.systemui.communal.widgets.CommunalAppWidgetHost
import com.android.systemui.communal.widgets.CommunalWidgetHost
@@ -69,6 +73,15 @@
* @param widgetIdToPriorityMap mapping of the widget ids to the priority of the widget.
*/
fun updateWidgetOrder(widgetIdToPriorityMap: Map<Int, Int>) {}
+
+ /**
+ * Restores the database by reading a state file from disk and updating the widget ids according
+ * to [oldToNewWidgetIdMap].
+ */
+ fun restoreWidgets(oldToNewWidgetIdMap: Map<Int, Int>)
+
+ /** Aborts the restore process and removes files from disk if necessary. */
+ fun abortRestoreWidgets()
}
@SysUISingleton
@@ -82,6 +95,8 @@
private val communalWidgetHost: CommunalWidgetHost,
private val communalWidgetDao: CommunalWidgetDao,
@CommunalLog logBuffer: LogBuffer,
+ private val backupManager: BackupManager,
+ private val backupUtils: CommunalBackupUtils,
) : CommunalWidgetRepository {
companion object {
const val TAG = "CommunalWidgetRepository"
@@ -143,6 +158,7 @@
provider = provider,
priority = priority,
)
+ backupManager.dataChanged()
} else {
appWidgetHost.deleteAppWidgetId(id)
}
@@ -155,6 +171,7 @@
if (communalWidgetDao.deleteWidgetById(widgetId)) {
appWidgetHost.deleteAppWidgetId(widgetId)
logger.i("Deleted widget with id $widgetId.")
+ backupManager.dataChanged()
}
}
}
@@ -165,6 +182,76 @@
logger.i({ "Updated the order of widget list with ids: $str1." }) {
str1 = widgetIdToPriorityMap.toString()
}
+ backupManager.dataChanged()
+ }
+ }
+
+ override fun restoreWidgets(oldToNewWidgetIdMap: Map<Int, Int>) {
+ bgScope.launch {
+ // Read restored state file from disk
+ val state: CommunalHubState
+ try {
+ state = backupUtils.readBytesFromDisk().toCommunalHubState()
+ } catch (e: Exception) {
+ logger.e({ "Failed reading restore data from disk: $str1" }) {
+ str1 = e.localizedMessage
+ }
+ abortRestoreWidgets()
+ return@launch
+ }
+
+ val widgetsWithHost = appWidgetHost.appWidgetIds.toList()
+ val widgetsToRemove = widgetsWithHost.toMutableList()
+
+ // Produce a new state to be restored, skipping invalid widgets
+ val newWidgets =
+ state.widgets.mapNotNull { restoredWidget ->
+ val newWidgetId =
+ oldToNewWidgetIdMap[restoredWidget.widgetId] ?: restoredWidget.widgetId
+
+ // Skip if widget id is not registered with the host
+ if (!widgetsWithHost.contains(newWidgetId)) {
+ logger.d({
+ "Skipped restoring widget (old:$int1 new:$int2) " +
+ "because it is not registered with host"
+ }) {
+ int1 = restoredWidget.widgetId
+ int2 = newWidgetId
+ }
+ return@mapNotNull null
+ }
+
+ widgetsToRemove.remove(newWidgetId)
+
+ CommunalHubState.CommunalWidgetItem().apply {
+ widgetId = newWidgetId
+ componentName = restoredWidget.componentName
+ rank = restoredWidget.rank
+ }
+ }
+ val newState = CommunalHubState().apply { widgets = newWidgets.toTypedArray() }
+
+ // Restore database
+ logger.i("Restoring communal database $newState")
+ communalWidgetDao.restoreCommunalHubState(newState)
+
+ // Delete restored state file from disk
+ backupUtils.clear()
+
+ // Remove widgets from host that have not been restored
+ widgetsToRemove.forEach { widgetId ->
+ logger.i({ "Deleting widget $int1 from host since it has not been restored" }) {
+ int1 = widgetId
+ }
+ appWidgetHost.deleteAppWidgetId(widgetId)
+ }
+ }
+ }
+
+ override fun abortRestoreWidgets() {
+ bgScope.launch {
+ logger.i("Restore widgets aborted")
+ backupUtils.clear()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
index 619e052..7448e14 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
@@ -170,6 +170,23 @@
}
/**
+ * Repopulates the communal widgets database by first reading a backed-up state from disk and
+ * updating the widget ids indicated by [oldToNewWidgetIdMap]. The backed-up state is removed
+ * from disk afterwards.
+ */
+ fun restoreWidgets(oldToNewWidgetIdMap: Map<Int, Int>) {
+ widgetRepository.restoreWidgets(oldToNewWidgetIdMap)
+ }
+
+ /**
+ * Aborts the task of restoring widgets from a backup. The backed up state stored on disk is
+ * removed.
+ */
+ fun abortRestoreWidgets() {
+ widgetRepository.abortRestoreWidgets()
+ }
+
+ /**
* Updates the transition state of the hub [SceneTransitionLayout].
*
* Note that you must call is with `null` when the UI is done or risk a memory leak.
diff --git a/packages/SystemUI/src/com/android/systemui/communal/proto/CommunalHubStateExt.kt b/packages/SystemUI/src/com/android/systemui/communal/proto/CommunalHubStateExt.kt
new file mode 100644
index 0000000..2d661cd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/proto/CommunalHubStateExt.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 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.communal.proto
+
+import com.android.systemui.communal.nano.CommunalHubState
+import com.google.protobuf.nano.InvalidProtocolBufferNanoException
+
+/** Converts a [CommunalHubState] to bytes. */
+fun CommunalHubState.toByteArray(): ByteArray {
+ return CommunalHubState.toByteArray(this)
+}
+
+/**
+ * Converts bytes to a [CommunalHubState].
+ *
+ * @throws InvalidProtocolBufferNanoException if parsing fails.
+ */
+fun ByteArray.toCommunalHubState(): CommunalHubState {
+ return CommunalHubState.parseFrom(this)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/proto/communal_hub_state.proto b/packages/SystemUI/src/com/android/systemui/communal/proto/communal_hub_state.proto
new file mode 100644
index 0000000..0816259
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/proto/communal_hub_state.proto
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+syntax = "proto3";
+
+package com.android.systemui.communal;
+
+option java_multiple_files = true;
+
+// Represents the state of communal hub for backup & restore.
+message CommunalHubState {
+ // Widgets in the communal hub.
+ repeated CommunalWidgetItem widgets = 1;
+
+ // Represents a widget in the communal hub.
+ message CommunalWidgetItem {
+ // Id of the widget.
+ int32 widget_id = 1;
+
+ // Component name of the widget.
+ string component_name = 2;
+
+ // Rank or order of the widget in the communal hub.
+ int32 rank = 3;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
index c73d738..f13b5759 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt
@@ -30,7 +30,6 @@
import com.android.systemui.media.controls.ui.view.MediaHostState
import com.android.systemui.media.dagger.MediaModule
import com.android.systemui.shade.domain.interactor.ShadeInteractor
-import com.android.systemui.util.kotlin.BooleanFlowOperators.not
import javax.inject.Inject
import javax.inject.Named
import kotlinx.coroutines.CoroutineScope
@@ -57,7 +56,7 @@
@Application private val scope: CoroutineScope,
private val communalInteractor: CommunalInteractor,
tutorialInteractor: CommunalTutorialInteractor,
- shadeInteractor: ShadeInteractor,
+ private val shadeInteractor: ShadeInteractor,
deviceEntryInteractor: DeviceEntryInteractor,
@Named(MediaModule.COMMUNAL_HUB) mediaHost: MediaHost,
@CommunalLog logBuffer: LogBuffer,
@@ -103,9 +102,6 @@
val isEnableWorkProfileDialogShowing: Flow<Boolean> =
_isEnableWorkProfileDialogShowing.asStateFlow()
- /** Whether touches should be disabled in communal */
- val touchesAllowed: Flow<Boolean> = not(shadeInteractor.isAnyFullyExpanded)
-
val deviceUnlocked: Flow<Boolean> = deviceEntryInteractor.isUnlocked
init {
@@ -192,6 +188,11 @@
delayedHidePopupJob = null
}
+ /** Whether we can transition to a new scene based on a user gesture. */
+ fun canChangeScene(): Boolean {
+ return !shadeInteractor.isAnyFullyExpanded.value
+ }
+
companion object {
const val POPUP_AUTO_HIDE_TIMEOUT_MS = 12000L
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalWidgetModule.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalWidgetModule.kt
index 60fb8d4..aa6516d 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalWidgetModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/CommunalWidgetModule.kt
@@ -38,7 +38,7 @@
@Module
interface CommunalWidgetModule {
companion object {
- private const val APP_WIDGET_HOST_ID = 116
+ const val APP_WIDGET_HOST_ID = 116
const val DEFAULT_WIDGETS = "default_widgets"
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
index 00a8259..3e98fc1 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ReferenceSystemUIModule.java
@@ -23,6 +23,7 @@
import android.hardware.SensorPrivacyManager;
import com.android.keyguard.KeyguardViewController;
+import com.android.systemui.CoreStartable;
import com.android.systemui.ScreenDecorationsModule;
import com.android.systemui.accessibility.SystemActionsModule;
import com.android.systemui.battery.BatterySaverModule;
@@ -50,12 +51,15 @@
import com.android.systemui.settings.MultiUserUtilsModule;
import com.android.systemui.shade.NotificationShadeWindowControllerImpl;
import com.android.systemui.shade.ShadeModule;
+import com.android.systemui.startable.Dependencies;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyboardShortcutsModule;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.dagger.StartCentralSurfacesModule;
+import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.phone.HeadsUpModule;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -77,6 +81,10 @@
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
+
+import java.util.Set;
import javax.inject.Named;
@@ -199,4 +207,13 @@
@Binds
abstract DozeHost provideDozeHost(DozeServiceHost dozeServiceHost);
+
+ /** */
+ @Provides
+ @IntoMap
+ @Dependencies
+ @ClassKey(SysuiStatusBarStateController.class)
+ static Set<Class<? extends CoreStartable>> providesStatusBarStateControllerDeps() {
+ return Set.of(CentralSurfaces.class);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index 871ef1e..1dd3722 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -94,7 +94,7 @@
Builder setTaskViewFactory(Optional<TaskViewFactory> t);
@BindsInstance
- Builder setTransitions(ShellTransitions t);
+ Builder setShellTransitions(ShellTransitions t);
@BindsInstance
Builder setKeyguardTransitions(KeyguardTransitions k);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index 23fc8ac..593196c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -25,6 +25,7 @@
import com.android.systemui.biometrics.BiometricNotificationService
import com.android.systemui.clipboardoverlay.ClipboardListener
import com.android.systemui.communal.CommunalDreamStartable
+import com.android.systemui.communal.CommunalBackupRestoreStartable
import com.android.systemui.communal.CommunalSceneStartable
import com.android.systemui.communal.log.CommunalLoggerStartable
import com.android.systemui.communal.widgets.CommunalAppWidgetHostStartable
@@ -342,6 +343,13 @@
@Binds
@IntoMap
+ @ClassKey(CommunalBackupRestoreStartable::class)
+ abstract fun bindCommunalBackupRestoreStartable(
+ impl: CommunalBackupRestoreStartable
+ ): CoreStartable
+
+ @Binds
+ @IntoMap
@ClassKey(HomeControlsDreamStartable::class)
abstract fun bindHomeControlsDreamStartable(impl: HomeControlsDreamStartable): CoreStartable
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 93864799..3462164 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -18,6 +18,7 @@
import android.app.INotificationManager;
import android.app.Service;
+import android.app.backup.BackupManager;
import android.content.Context;
import android.service.dreams.IDreamManager;
@@ -318,6 +319,13 @@
return new Monitor(executor, Collections.singleton(systemProcessCondition), logBuffer);
}
+ /** Provides the package name for SystemUI. */
+ @SysUISingleton
+ @Provides
+ static BackupManager provideBackupManager(@Application Context context) {
+ return new BackupManager(context);
+ }
+
@BindsOptionalOf
abstract CommandQueue optionalCommandQueue();
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
index e04a0e5..a3cdb2e 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -94,7 +94,7 @@
Optional<TaskViewFactory> getTaskViewFactory();
@WMSingleton
- ShellTransitions getTransitions();
+ ShellTransitions getShellTransitions();
@WMSingleton
KeyguardTransitions getKeyguardTransitions();
diff --git a/packages/SystemUI/src/com/android/systemui/demomode/DemoMode.java b/packages/SystemUI/src/com/android/systemui/demomode/DemoMode.java
index 672ade2..3021184 100644
--- a/packages/SystemUI/src/com/android/systemui/demomode/DemoMode.java
+++ b/packages/SystemUI/src/com/android/systemui/demomode/DemoMode.java
@@ -37,6 +37,15 @@
return NO_COMMANDS;
}
+ /** Something simple enough to be recognizable in dumpsys logs */
+ default String logName() {
+ if (this.getClass().isAnonymousClass()) {
+ return getClass().getName();
+ } else {
+ return getClass().getSimpleName();
+ }
+ }
+
String ACTION_DEMO = "com.android.systemui.demo";
String EXTRA_COMMAND = "command";
diff --git a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
index 45ff963..f03aa63 100644
--- a/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
+++ b/packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
@@ -25,12 +25,12 @@
import android.util.Log
import com.android.systemui.Dumpable
import com.android.systemui.broadcast.BroadcastDispatcher
-import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.demomode.DemoMode.ACTION_DEMO
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.policy.CallbackController
import com.android.systemui.util.Assert
import com.android.systemui.util.settings.GlobalSettings
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
import java.io.PrintWriter
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
@@ -209,20 +209,18 @@
pw.println("DemoModeController state -")
pw.println(" isInDemoMode=$isInDemoMode")
pw.println(" isDemoModeAllowed=$isAvailable")
- pw.print(" receivers=[")
- val copy: List<DemoModeCommandReceiver>
+ val copy: List<DemoMode>
synchronized(this) { copy = receivers.toList() }
- copy.forEach { recv -> pw.print(" ${recv.javaClass.simpleName}") }
- pw.println(" ]")
+
+ // List of all receivers
+ pw.println(" receivers=[${copy.joinToString(", ") { it.logName() }}]")
+
+ // Print out the map of COMMAND -> list of receivers for that command
pw.println(" receiverMap= [")
- receiverMap.keys.forEach { command ->
- pw.print(" $command : [")
- val recvs =
- receiverMap[command]!!
- .map { receiver -> receiver.javaClass.simpleName }
- .joinToString(",")
- pw.println("$recvs ]")
+ receiverMap.entries.forEach { (comm, recv) ->
+ pw.println(" $comm : [${recv.joinToString(", ") {it.logName()}}]")
}
+ pw.println(" ]")
}
private val tracker =
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractor.kt
index 7733de4..a32b2aa 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractor.kt
@@ -68,6 +68,7 @@
fun onPrimaryBouncerUserInput()
fun onAccessibilityAction()
fun onWalletLaunched()
+ fun onDeviceUnfolded()
/** Whether face auth is considered class 3 */
fun isFaceAuthStrong(): Boolean
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/NoopDeviceEntryFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/NoopDeviceEntryFaceAuthInteractor.kt
index 65f3eb7..6629f6e 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/NoopDeviceEntryFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/NoopDeviceEntryFaceAuthInteractor.kt
@@ -66,4 +66,5 @@
override fun onPrimaryBouncerUserInput() {}
override fun onAccessibilityAction() {}
override fun onWalletLaunched() = Unit
+ override fun onDeviceUnfolded() {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt
index 03819ed..6c6683a 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt
@@ -37,6 +37,7 @@
import com.android.systemui.deviceentry.shared.model.FaceAuthenticationStatus
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
+import com.android.systemui.keyguard.shared.model.DevicePosture
import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
@@ -248,6 +249,12 @@
}
}
+ override fun onDeviceUnfolded() {
+ if (facePropertyRepository.supportedPostures.contains(DevicePosture.OPENED)) {
+ runFaceAuth(FaceAuthUiEvent.FACE_AUTH_UPDATED_POSTURE_CHANGED, true)
+ }
+ }
+
override fun registerListener(listener: FaceAuthenticationListener) {
listeners.add(listener)
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
index 5a036b1..0c2709e 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayContainerViewController.java
@@ -22,6 +22,7 @@
import static com.android.systemui.complication.ComplicationLayoutParams.POSITION_BOTTOM;
import static com.android.systemui.complication.ComplicationLayoutParams.POSITION_TOP;
import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
+import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
import android.animation.Animator;
import android.content.res.Resources;
@@ -40,6 +41,8 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
import com.android.systemui.dreams.dagger.DreamOverlayModule;
+import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
+import com.android.systemui.keyguard.shared.model.KeyguardState;
import com.android.systemui.res.R;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.statusbar.BlurUtils;
@@ -50,6 +53,8 @@
import javax.inject.Inject;
import javax.inject.Named;
+import kotlinx.coroutines.CoroutineDispatcher;
+
/**
* View controller for {@link DreamOverlayContainerView}.
*/
@@ -62,6 +67,7 @@
private final DreamOverlayAnimationsController mDreamOverlayAnimationsController;
private final DreamOverlayStateController mStateController;
private final LowLightTransitionCoordinator mLowLightTransitionCoordinator;
+ private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
private final ComplicationHostViewController mComplicationHostViewController;
@@ -81,6 +87,7 @@
// Main thread handler used to schedule periodic tasks (e.g. burn-in protection updates).
private final Handler mHandler;
+ private final CoroutineDispatcher mMainDispatcher;
private final int mDreamOverlayMaxTranslationY;
private final PrimaryBouncerCallbackInteractor mPrimaryBouncerCallbackInteractor;
@@ -88,6 +95,7 @@
private boolean mBouncerAnimating;
private boolean mWakingUpFromSwipe;
+ private boolean mAnyBouncerShowing;
private final BouncerlessScrimController mBouncerlessScrimController;
@@ -170,6 +178,7 @@
LowLightTransitionCoordinator lowLightTransitionCoordinator,
BlurUtils blurUtils,
@Main Handler handler,
+ @Main CoroutineDispatcher mainDispatcher,
@Main Resources resources,
@Named(DreamOverlayModule.MAX_BURN_IN_OFFSET) int maxBurnInOffset,
@Named(DreamOverlayModule.BURN_IN_PROTECTION_UPDATE_INTERVAL) long
@@ -178,7 +187,8 @@
PrimaryBouncerCallbackInteractor primaryBouncerCallbackInteractor,
DreamOverlayAnimationsController animationsController,
DreamOverlayStateController stateController,
- BouncerlessScrimController bouncerlessScrimController) {
+ BouncerlessScrimController bouncerlessScrimController,
+ KeyguardTransitionInteractor keyguardTransitionInteractor) {
super(containerView);
mDreamOverlayContentView = contentView;
mStatusBarViewController = statusBarViewController;
@@ -190,6 +200,8 @@
mBouncerlessScrimController = bouncerlessScrimController;
mBouncerlessScrimController.addCallback(mBouncerlessExpansionCallback);
+ mKeyguardTransitionInteractor = keyguardTransitionInteractor;
+
mComplicationHostViewController = complicationHostViewController;
mDreamOverlayMaxTranslationY = resources.getDimensionPixelSize(
R.dimen.dream_overlay_y_offset);
@@ -200,6 +212,7 @@
ViewGroup.LayoutParams.MATCH_PARENT));
mHandler = handler;
+ mMainDispatcher = mainDispatcher;
mMaxBurnInOffset = maxBurnInOffset;
mBurnInProtectionUpdateInterval = burnInProtectionUpdateInterval;
mMillisUntilFullJitter = millisUntilFullJitter;
@@ -225,6 +238,12 @@
mView.getRootSurfaceControl().setTouchableRegion(emptyRegion);
emptyRegion.recycle();
+ collectFlow(
+ mView,
+ mKeyguardTransitionInteractor.isFinishedInStateWhere(KeyguardState::isBouncerState),
+ isFinished -> mAnyBouncerShowing = isFinished,
+ mMainDispatcher);
+
// Start dream entry animations. Skip animations for low light clock.
if (!mStateController.isLowLightActive()) {
// If this is transitioning from the low light dream to the user dream, the overlay
@@ -246,6 +265,10 @@
return mView;
}
+ boolean isBouncerShowing() {
+ return mAnyBouncerShowing;
+ }
+
private void updateBurnInOffsets() {
// Make sure the offset starts at zero, to avoid a big jump in the overlay when it first
// appears.
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index 1135afe..a9ef531 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -19,9 +19,11 @@
import static com.android.systemui.dreams.dagger.DreamModule.DREAM_OVERLAY_WINDOW_TITLE;
import static com.android.systemui.dreams.dagger.DreamModule.DREAM_TOUCH_INSET_MANAGER;
import static com.android.systemui.dreams.dagger.DreamModule.HOME_CONTROL_PANEL_DREAM_COMPONENT;
+import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.util.Log;
import android.view.View;
@@ -34,7 +36,10 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
+import androidx.lifecycle.LifecycleService;
+import androidx.lifecycle.ServiceLifecycleDispatcher;
import androidx.lifecycle.ViewModelStore;
import com.android.dream.lowlight.dagger.LowLightDreamModule;
@@ -45,15 +50,21 @@
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.ambient.touch.TouchMonitor;
import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent;
+import com.android.systemui.ambient.touch.scrim.ScrimManager;
+import com.android.systemui.communal.domain.interactor.CommunalInteractor;
+import com.android.systemui.communal.shared.model.CommunalScenes;
import com.android.systemui.complication.Complication;
import com.android.systemui.complication.dagger.ComplicationComponent;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.dagger.DreamOverlayComponent;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
+import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.touch.TouchInsetManager;
import com.android.systemui.util.concurrency.DelayableExecutor;
import java.util.Arrays;
import java.util.HashSet;
+import java.util.function.Consumer;
import javax.inject.Inject;
import javax.inject.Named;
@@ -63,7 +74,8 @@
* dream reaches directly out to the service with a Window reference (via LayoutParams), which the
* service uses to insert its own child Window into the dream's parent Window.
*/
-public class DreamOverlayService extends android.service.dreams.DreamOverlayService {
+public class DreamOverlayService extends android.service.dreams.DreamOverlayService implements
+ LifecycleOwner {
private static final String TAG = "DreamOverlayService";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -76,6 +88,7 @@
private DreamOverlayContainerViewController mDreamOverlayContainerViewController;
private final DreamOverlayCallbackController mDreamOverlayCallbackController;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ private final ScrimManager mScrimManager;
@Nullable
private final ComponentName mLowLightDreamComponent;
@Nullable
@@ -93,6 +106,21 @@
// True if the service has been destroyed.
private boolean mDestroyed = false;
+ /**
+ * True if the notification shade is open.
+ */
+ private boolean mShadeExpanded = false;
+
+ /**
+ * True if any part of the glanceable hub is visible.
+ */
+ private boolean mCommunalVisible = false;
+
+ /**
+ * True if the primary bouncer is visible.
+ */
+ private boolean mBouncerShowing = false;
+
private final ComplicationComponent mComplicationComponent;
private final AmbientTouchComponent mAmbientTouchComponent;
@@ -102,27 +130,72 @@
private final DreamOverlayComponent mDreamOverlayComponent;
- private final DreamOverlayLifecycleOwner mLifecycleOwner;
+ /**
+ * This {@link LifecycleRegistry} controls when dream overlay functionality, like touch
+ * handling, should be active. It will automatically be paused when the dream overlay is hidden
+ * while dreaming, such as when the notification shade, bouncer, or glanceable hub are visible.
+ */
private final LifecycleRegistry mLifecycleRegistry;
+ /**
+ * Drives the lifecycle exposed by this service's {@link #getLifecycle()}.
+ * <p>
+ * Used to mimic a {@link LifecycleService}, though we do not update the lifecycle in
+ * {@link #onBind(Intent)} since it's final in the base class.
+ */
+ private final ServiceLifecycleDispatcher mDispatcher = new ServiceLifecycleDispatcher(this);
+
private TouchMonitor mTouchMonitor;
+ private final CommunalInteractor mCommunalInteractor;
+
+ private final SystemDialogsCloser mSystemDialogsCloser;
+
private final KeyguardUpdateMonitorCallback mKeyguardCallback =
new KeyguardUpdateMonitorCallback() {
@Override
public void onShadeExpandedChanged(boolean expanded) {
mExecutor.execute(() -> {
- if (getCurrentStateLocked() != Lifecycle.State.RESUMED
- && getCurrentStateLocked() != Lifecycle.State.STARTED) {
+ if (mShadeExpanded == expanded) {
return;
}
+ mShadeExpanded = expanded;
- setCurrentStateLocked(
- expanded ? Lifecycle.State.STARTED : Lifecycle.State.RESUMED);
+ updateLifecycleStateLocked();
});
}
};
+ private final Consumer<Boolean> mCommunalVisibleConsumer = new Consumer<>() {
+ @Override
+ public void accept(Boolean communalVisible) {
+ mExecutor.execute(() -> {
+ if (mCommunalVisible == communalVisible) {
+ return;
+ }
+
+ mCommunalVisible = communalVisible;
+
+ updateLifecycleStateLocked();
+ });
+ }
+ };
+
+ private final Consumer<Boolean> mBouncerShowingConsumer = new Consumer<>() {
+ @Override
+ public void accept(Boolean bouncerShowing) {
+ mExecutor.execute(() -> {
+ if (mBouncerShowing == bouncerShowing) {
+ return;
+ }
+
+ mBouncerShowing = bouncerShowing;
+
+ updateLifecycleStateLocked();
+ });
+ }
+ };
+
private final DreamOverlayStateController.Callback mExitAnimationFinishedCallback =
new DreamOverlayStateController.Callback() {
@Override
@@ -168,19 +241,24 @@
AmbientTouchComponent.Factory ambientTouchComponentFactory,
DreamOverlayStateController stateController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
+ ScrimManager scrimManager,
+ CommunalInteractor communalInteractor,
+ SystemDialogsCloser systemDialogsCloser,
UiEventLogger uiEventLogger,
@Named(DREAM_TOUCH_INSET_MANAGER) TouchInsetManager touchInsetManager,
@Nullable @Named(LowLightDreamModule.LOW_LIGHT_DREAM_COMPONENT)
- ComponentName lowLightDreamComponent,
+ ComponentName lowLightDreamComponent,
@Nullable @Named(HOME_CONTROL_PANEL_DREAM_COMPONENT)
- ComponentName homeControlPanelDreamComponent,
+ ComponentName homeControlPanelDreamComponent,
DreamOverlayCallbackController dreamOverlayCallbackController,
+ KeyguardInteractor keyguardInteractor,
@Named(DREAM_OVERLAY_WINDOW_TITLE) String windowTitle) {
super(executor);
mContext = context;
mExecutor = executor;
mWindowManager = windowManager;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+ mScrimManager = scrimManager;
mLowLightDreamComponent = lowLightDreamComponent;
mHomeControlPanelDreamComponent = homeControlPanelDreamComponent;
mKeyguardUpdateMonitor.registerCallback(mKeyguardCallback);
@@ -188,6 +266,8 @@
mUiEventLogger = uiEventLogger;
mDreamOverlayCallbackController = dreamOverlayCallbackController;
mWindowTitle = windowTitle;
+ mCommunalInteractor = communalInteractor;
+ mSystemDialogsCloser = systemDialogsCloser;
final ViewModelStore viewModelStore = new ViewModelStore();
final Complication.Host host =
@@ -203,10 +283,32 @@
new HashSet<>(Arrays.asList(
mDreamComplicationComponent.getHideComplicationTouchHandler(),
mDreamOverlayComponent.getCommunalTouchHandler())));
- mLifecycleOwner = lifecycleOwner;
- mLifecycleRegistry = mLifecycleOwner.getRegistry();
+ mLifecycleRegistry = lifecycleOwner.getRegistry();
- mExecutor.execute(() -> setCurrentStateLocked(Lifecycle.State.CREATED));
+ mExecutor.execute(() -> setLifecycleStateLocked(Lifecycle.State.CREATED));
+
+ collectFlow(getLifecycle(), communalInteractor.isCommunalVisible(),
+ mCommunalVisibleConsumer);
+ collectFlow(getLifecycle(), keyguardInteractor.primaryBouncerShowing,
+ mBouncerShowingConsumer);
+ }
+
+ @NonNull
+ @Override
+ public Lifecycle getLifecycle() {
+ return mDispatcher.getLifecycle();
+ }
+
+ @Override
+ public void onCreate() {
+ mDispatcher.onServicePreSuperOnCreate();
+ super.onCreate();
+ }
+
+ @Override
+ public void onStart(Intent intent, int startId) {
+ mDispatcher.onServicePreSuperOnStart();
+ super.onStart(intent, startId);
}
@Override
@@ -214,19 +316,20 @@
mKeyguardUpdateMonitor.removeCallback(mKeyguardCallback);
mExecutor.execute(() -> {
- setCurrentStateLocked(Lifecycle.State.DESTROYED);
+ setLifecycleStateLocked(Lifecycle.State.DESTROYED);
resetCurrentDreamOverlayLocked();
mDestroyed = true;
});
+ mDispatcher.onServicePreSuperOnDestroy();
super.onDestroy();
}
@Override
public void onStartDream(@NonNull WindowManager.LayoutParams layoutParams) {
- setCurrentStateLocked(Lifecycle.State.STARTED);
+ setLifecycleStateLocked(Lifecycle.State.STARTED);
mUiEventLogger.log(DreamOverlayEvent.DREAM_OVERLAY_ENTER_START);
@@ -256,7 +359,7 @@
return;
}
- setCurrentStateLocked(Lifecycle.State.RESUMED);
+ setLifecycleStateLocked(Lifecycle.State.RESUMED);
mStateController.setOverlayActive(true);
final ComponentName dreamComponent = getDreamComponent();
mStateController.setLowLightActive(
@@ -276,14 +379,27 @@
resetCurrentDreamOverlayLocked();
}
- private Lifecycle.State getCurrentStateLocked() {
+ private Lifecycle.State getLifecycleStateLocked() {
return mLifecycleRegistry.getCurrentState();
}
- private void setCurrentStateLocked(Lifecycle.State state) {
+ private void setLifecycleStateLocked(Lifecycle.State state) {
mLifecycleRegistry.setCurrentState(state);
}
+ private void updateLifecycleStateLocked() {
+ if (getLifecycleStateLocked() != Lifecycle.State.RESUMED
+ && getLifecycleStateLocked() != Lifecycle.State.STARTED) {
+ return;
+ }
+
+ // If anything is on top of the dream, we should stop touch handling.
+ boolean shouldPause = mShadeExpanded || mCommunalVisible || mBouncerShowing;
+
+ setLifecycleStateLocked(
+ shouldPause ? Lifecycle.State.STARTED : Lifecycle.State.RESUMED);
+ }
+
@Override
public void onWakeUp() {
if (mDreamOverlayContainerViewController != null) {
@@ -292,6 +408,28 @@
}
}
+ @Override
+ public void onComeToFront() {
+ // Make sure the bouncer is closed. Expanding the shade effectively contracts the bouncer
+ // an equal amount.
+ if (mDreamOverlayContainerViewController != null
+ && mDreamOverlayContainerViewController.isBouncerShowing()) {
+ mScrimManager.getCurrentController().expand(
+ new ShadeExpansionChangeEvent(
+ /* fraction= */ 1.f,
+ /* expanded= */ false,
+ /* tracking= */ true));
+ }
+
+ // closeSystemDialogs takes care of closing anything that responds to the
+ // {@link Intent.ACTION_CLOSE_SYSTEM_DIALOGS} broadcast (which includes the notification
+ // shade).
+ mSystemDialogsCloser.closeSystemDialogs();
+
+ // Hide glanceable hub (this is a nop if glanceable hub is not open).
+ mCommunalInteractor.changeScene(CommunalScenes.Blank, null);
+ }
+
/**
* Inserts {@link Window} to host the dream overlay into the dream's parent window. Must be
* called from the main executing thread. The window attributes closely mirror those that are
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt b/packages/SystemUI/src/com/android/systemui/dreams/SystemDialogsCloser.java
similarity index 71%
copy from packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
copy to packages/SystemUI/src/com/android/systemui/dreams/SystemDialogsCloser.java
index c4476fc..6e7239a4 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/SystemDialogsCloser.java
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.volume.panel.component.mediaoutput.shared.model
+package com.android.systemui.dreams;
-import android.media.session.PlaybackState
-
-data class SessionWithPlayback(
- val session: MediaDeviceSession,
- val playback: PlaybackState,
-)
+/** Defines an interface for a class that is responsible for closing system dialogs. */
+public interface SystemDialogsCloser {
+ /** Close any open system dialogs. */
+ void closeSystemDialogs();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
index 31710ac..516b8c5 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -31,6 +31,7 @@
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.DreamOverlayNotificationCountProvider;
import com.android.systemui.dreams.DreamOverlayService;
+import com.android.systemui.dreams.SystemDialogsCloser;
import com.android.systemui.dreams.complication.dagger.ComplicationComponent;
import com.android.systemui.dreams.homecontrols.DreamActivityProvider;
import com.android.systemui.dreams.homecontrols.DreamActivityProviderImpl;
@@ -146,6 +147,15 @@
return Optional.empty();
}
+ /**
+ * Provides an implementation for {@link SystemDialogsCloser} that calls
+ * {@link Context.closeSystemDialogs}.
+ */
+ @Provides
+ static SystemDialogsCloser providesSystemDialogsCloser(Context context) {
+ return () -> context.closeSystemDialogs();
+ }
+
/** */
@Provides
@Named(DREAM_ONLY_ENABLED_FOR_DOCK_USER)
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java
index 1c047dd..fff0c58 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/CommunalTouchHandler.java
@@ -98,7 +98,7 @@
// Notification shade window has its own logic to be visible if the hub is open, no need to
// do anything here other than send touch events over.
session.registerInputListener(ev -> {
- surfaces.handleDreamTouch((MotionEvent) ev);
+ surfaces.handleExternalShadeWindowTouch((MotionEvent) ev);
if (ev != null && ((MotionEvent) ev).getAction() == MotionEvent.ACTION_UP) {
var unused = session.pop();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt
index 2d9c14e..221f790 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/ui/viewmodel/DreamViewModel.kt
@@ -47,7 +47,7 @@
configurationInteractor: ConfigurationInteractor,
keyguardTransitionInteractor: KeyguardTransitionInteractor,
fromGlanceableHubTransitionInteractor: GlanceableHubToDreamingTransitionViewModel,
- private val toGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel,
+ toGlanceableHubTransitionViewModel: DreamingToGlanceableHubTransitionViewModel,
private val toLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel,
private val communalInteractor: CommunalInteractor,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
@@ -60,7 +60,6 @@
communalInteractor.isCommunalEnabled.value &&
!keyguardUpdateMonitor.isEncryptedOrLockdown(userTracker.userId)
if (showGlanceableHub) {
- toGlanceableHubTransitionViewModel.startTransition()
communalInteractor.changeScene(CommunalScenes.Communal)
} else {
toLockscreenTransitionViewModel.startTransition()
diff --git a/packages/SystemUI/src/com/android/systemui/graphics/ImageLoader.kt b/packages/SystemUI/src/com/android/systemui/graphics/ImageLoader.kt
index 2856011..567bf70 100644
--- a/packages/SystemUI/src/com/android/systemui/graphics/ImageLoader.kt
+++ b/packages/SystemUI/src/com/android/systemui/graphics/ImageLoader.kt
@@ -339,7 +339,7 @@
}
// Fallback to non-ImageDecoder load if the attempt failed (e.g. the resource
// is a Vector drawable which ImageDecoder doesn't support.)
- ?: icon.loadDrawable(context)
+ ?: loadIconDrawable(icon, context)
}
Icon.TYPE_BITMAP -> {
BitmapDrawable(context.resources, icon.bitmap)
@@ -357,7 +357,7 @@
}
else -> {
// We don't recognize this icon, just fallback.
- icon.loadDrawable(context)
+ loadIconDrawable(icon, context)
}
}?.let { drawable ->
// Icons carry tint which we need to propagate down to a Drawable.
@@ -366,6 +366,14 @@
}
}
+ @WorkerThread
+ fun loadIconDrawable(icon: Icon, context: Context): Drawable? {
+ icon.loadDrawable(context)?.let { return it }
+
+ Log.w(TAG, "Failed to load drawable for $icon")
+ return null
+ }
+
/**
* Obtains the image size from the image header, without decoding the full image.
*
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/HapticSliderViewBinder.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/HapticSliderViewBinder.kt
index 304fdd6..ca6c8da 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/HapticSliderViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/HapticSliderViewBinder.kt
@@ -23,11 +23,11 @@
object HapticSliderViewBinder {
/**
- * Binds a [SeekableSliderHapticPlugin] to a [View]. The binded view should be a
+ * Binds a [SeekbarHapticPlugin] to a [View]. The binded view should be a
* [android.widget.SeekBar] or a container of a [android.widget.SeekBar]
*/
@JvmStatic
- fun bind(view: View?, plugin: SeekableSliderHapticPlugin) {
+ fun bind(view: View?, plugin: SeekbarHapticPlugin) {
view?.repeatWhenAttached {
plugin.startInScope(lifecycleScope)
try {
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderEventProducer.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderEventProducer.kt
deleted file mode 100644
index cfa5294..0000000
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderEventProducer.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2023 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.haptics.slider
-
-import android.widget.SeekBar
-import android.widget.SeekBar.OnSeekBarChangeListener
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.update
-
-/** An event producer for a Seekable element such as the Android [SeekBar] */
-class SeekableSliderEventProducer : SliderEventProducer, OnSeekBarChangeListener {
-
- /** The current event reported by a SeekBar */
- private val _currentEvent = MutableStateFlow(SliderEvent(SliderEventType.NOTHING, 0f))
-
- override fun produceEvents(): Flow<SliderEvent> = _currentEvent.asStateFlow()
-
- override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
- val eventType =
- if (fromUser) SliderEventType.PROGRESS_CHANGE_BY_USER
- else SliderEventType.PROGRESS_CHANGE_BY_PROGRAM
-
- _currentEvent.value = SliderEvent(eventType, normalizeProgress(seekBar, progress))
- }
-
- /**
- * Normalize the integer progress of a SeekBar to the range from 0F to 1F.
- *
- * @param[seekBar] The SeekBar that reports a progress.
- * @param[progress] The integer progress of the SeekBar within its min and max values.
- * @return The progress in the range from 0F to 1F.
- */
- private fun normalizeProgress(seekBar: SeekBar, progress: Int): Float {
- if (seekBar.max == seekBar.min) {
- return 1.0f
- }
- val range = seekBar.max - seekBar.min
- return (progress - seekBar.min) / range.toFloat()
- }
-
- override fun onStartTrackingTouch(seekBar: SeekBar) {
- _currentEvent.update { previousEvent ->
- SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, previousEvent.currentProgress)
- }
- }
-
- override fun onStopTrackingTouch(seekBar: SeekBar) {
- _currentEvent.update { previousEvent ->
- SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, previousEvent.currentProgress)
- }
- }
-
- /** The arrow navigation that was operating the slider has stopped. */
- fun onArrowUp() {
- _currentEvent.update { previousEvent ->
- SliderEvent(SliderEventType.ARROW_UP, previousEvent.currentProgress)
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderHapticPlugin.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekbarHapticPlugin.kt
similarity index 72%
rename from packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderHapticPlugin.kt
rename to packages/SystemUI/src/com/android/systemui/haptics/slider/SeekbarHapticPlugin.kt
index ed82278..2007db34 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderHapticPlugin.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekbarHapticPlugin.kt
@@ -30,12 +30,12 @@
/**
* A plugin added to a manager of a [android.widget.SeekBar] that adds dynamic haptic feedback.
*
- * A [SeekableSliderEventProducer] is used as the producer of slider events, a
+ * A [SliderStateProducer] is used as the producer of slider events, a
* [SliderHapticFeedbackProvider] is used as the listener of slider states to play haptic feedback
- * depending on the state, and a [SeekableSliderTracker] is used as the state machine handler that
+ * depending on the state, and a [SliderStateTracker] is used as the state machine handler that
* tracks and manipulates the slider state.
*/
-class SeekableSliderHapticPlugin
+class SeekbarHapticPlugin
@JvmOverloads
constructor(
vibratorHelper: VibratorHelper,
@@ -46,7 +46,7 @@
private val velocityTracker = VelocityTracker.obtain()
- private val sliderEventProducer = SeekableSliderEventProducer()
+ private val sliderEventProducer = SliderStateProducer()
private val sliderHapticFeedbackProvider =
SliderHapticFeedbackProvider(
@@ -56,7 +56,7 @@
systemClock,
)
- private var sliderTracker: SeekableSliderTracker? = null
+ private var sliderTracker: SliderStateTracker? = null
private var pluginScope: CoroutineScope? = null
@@ -86,7 +86,7 @@
fun startInScope(scope: CoroutineScope) {
if (sliderTracker != null) stop()
sliderTracker =
- SeekableSliderTracker(
+ SliderStateTracker(
sliderHapticFeedbackProvider,
sliderEventProducer,
scope,
@@ -116,28 +116,52 @@
/** onStartTrackingTouch event from the slider's [android.widget.SeekBar] */
fun onStartTrackingTouch(seekBar: SeekBar) {
if (isTracking) {
- sliderEventProducer.onStartTrackingTouch(seekBar)
+ sliderEventProducer.onStartTracking(true)
}
}
/** onProgressChanged event from the slider's [android.widget.SeekBar] */
fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
if (isTracking) {
- sliderEventProducer.onProgressChanged(seekBar, progress, fromUser)
+ if (sliderTracker?.currentState == SliderState.IDLE && !fromUser) {
+ // This case translates to the slider starting to track program changes
+ sliderEventProducer.resetWithProgress(normalizeProgress(seekBar, progress))
+ sliderEventProducer.onStartTracking(false)
+ } else {
+ sliderEventProducer.onProgressChanged(
+ fromUser,
+ normalizeProgress(seekBar, progress),
+ )
+ }
}
}
+ /**
+ * Normalize the integer progress of a SeekBar to the range from 0F to 1F.
+ *
+ * @param[seekBar] The SeekBar that reports a progress.
+ * @param[progress] The integer progress of the SeekBar within its min and max values.
+ * @return The progress in the range from 0F to 1F.
+ */
+ private fun normalizeProgress(seekBar: SeekBar, progress: Int): Float {
+ if (seekBar.max == seekBar.min) {
+ return 1.0f
+ }
+ val range = seekBar.max - seekBar.min
+ return (progress - seekBar.min) / range.toFloat()
+ }
+
/** onStopTrackingTouch event from the slider's [android.widget.SeekBar] */
fun onStopTrackingTouch(seekBar: SeekBar) {
if (isTracking) {
- sliderEventProducer.onStopTrackingTouch(seekBar)
+ sliderEventProducer.onStopTracking(true)
}
}
- /** onArrowUp event recorded */
- fun onArrowUp() {
+ /** Programmatic changes have stopped */
+ private fun onStoppedTrackingProgram() {
if (isTracking) {
- sliderEventProducer.onArrowUp()
+ sliderEventProducer.onStopTracking(false)
}
}
@@ -146,7 +170,7 @@
*
* This event is used to estimate the key-up event based on a running a timer as a waiting
* coroutine in the [pluginScope]. A key-up event in a slider corresponds to an onArrowUp event.
- * Therefore, [onArrowUp] must be called after the timeout.
+ * Therefore, [onStoppedTrackingProgram] must be called after the timeout.
*/
fun onKeyDown() {
if (!isTracking) return
@@ -158,7 +182,7 @@
keyUpJob =
pluginScope?.launch {
delay(KEY_UP_TIMEOUT)
- onArrowUp()
+ onStoppedTrackingProgram()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderEventType.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderEventType.kt
index 4a63941..0edef99 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderEventType.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderEventType.kt
@@ -22,6 +22,8 @@
NOTHING,
/* The slider has captured a touch input and is tracking touch events. */
STARTED_TRACKING_TOUCH,
+ /* The slider started tracking programmatic value changes */
+ STARTED_TRACKING_PROGRAM,
/* The slider progress is changing due to user touch input. */
PROGRESS_CHANGE_BY_USER,
/* The slider progress is changing programmatically. */
@@ -29,5 +31,5 @@
/* The slider has stopped tracking touch events. */
STOPPED_TRACKING_TOUCH,
/* The external (not touch) stimulus that was modifying the slider progress has stopped. */
- ARROW_UP,
+ STOPPED_TRACKING_PROGRAM,
}
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderStateProducer.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderStateProducer.kt
new file mode 100644
index 0000000..1124ab1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderStateProducer.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2024 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.haptics.slider
+
+import androidx.annotation.FloatRange
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.update
+
+/** A stateful producer of [SliderEvent] */
+class SliderStateProducer : SliderEventProducer {
+
+ /** The current event of a slider */
+ private val _currentEvent = MutableStateFlow(SliderEvent(SliderEventType.NOTHING, 0f))
+
+ override fun produceEvents(): Flow<SliderEvent> = _currentEvent.asStateFlow()
+
+ fun onProgressChanged(fromUser: Boolean, @FloatRange(from = 0.0, to = 1.0) progress: Float) {
+ val eventType =
+ if (fromUser) SliderEventType.PROGRESS_CHANGE_BY_USER
+ else SliderEventType.PROGRESS_CHANGE_BY_PROGRAM
+
+ _currentEvent.value = SliderEvent(eventType, progress)
+ }
+
+ fun onStartTracking(fromUser: Boolean) {
+ val eventType =
+ if (fromUser) SliderEventType.STARTED_TRACKING_TOUCH
+ else SliderEventType.STARTED_TRACKING_PROGRAM
+ _currentEvent.update { previousEvent ->
+ SliderEvent(eventType, previousEvent.currentProgress)
+ }
+ }
+
+ fun onStopTracking(fromUser: Boolean) {
+ val eventType =
+ if (fromUser) SliderEventType.STOPPED_TRACKING_TOUCH
+ else SliderEventType.STOPPED_TRACKING_PROGRAM
+ _currentEvent.update { previousEvent ->
+ SliderEvent(eventType, previousEvent.currentProgress)
+ }
+ }
+
+ fun resetWithProgress(@FloatRange(from = 0.0, to = 1.0) progress: Float) {
+ _currentEvent.value = SliderEvent(SliderEventType.NOTHING, progress)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderTracker.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderStateTracker.kt
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderTracker.kt
rename to packages/SystemUI/src/com/android/systemui/haptics/slider/SliderStateTracker.kt
index 0af3038..14cf411 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekableSliderTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderStateTracker.kt
@@ -25,11 +25,12 @@
import kotlinx.coroutines.launch
/**
- * Slider tracker attached to a seekable slider.
+ * Slider tracker attached to a slider.
*
- * The tracker runs a state machine to execute actions on touch-based events typical of a seekable
- * slider such as [android.widget.SeekBar]. Coroutines responsible for running the state machine,
- * collecting slider events and maintaining waiting states are run on the provided [CoroutineScope].
+ * The tracker runs a state machine to execute actions on touch-based events typical of a general
+ * slider (including a [android.widget.SeekBar]). Coroutines responsible for running the state
+ * machine, collecting slider events and maintaining waiting states are run on the provided
+ * [CoroutineScope].
*
* @param[sliderStateListener] Listener of the slider state.
* @param[sliderEventProducer] Producer of slider events arising from the slider.
@@ -37,7 +38,7 @@
* events and the launch of timer jobs.
* @property[config] Configuration parameters of the slider tracker.
*/
-class SeekableSliderTracker(
+class SliderStateTracker(
sliderStateListener: SliderStateListener,
sliderEventProducer: SliderEventProducer,
trackerScope: CoroutineScope,
@@ -79,7 +80,7 @@
// This will disambiguate between an imprecise touch that acquires the slider handle,
// and a select and jump operation in the slider track.
setState(SliderState.WAIT)
- } else if (newEventType == SliderEventType.PROGRESS_CHANGE_BY_PROGRAM) {
+ } else if (newEventType == SliderEventType.STARTED_TRACKING_PROGRAM) {
val state =
if (bookendReached(currentProgress)) SliderState.ARROW_HANDLE_REACHED_BOOKEND
else SliderState.ARROW_HANDLE_MOVED_ONCE
@@ -227,7 +228,7 @@
}
SliderEventType.PROGRESS_CHANGE_BY_PROGRAM ->
SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY
- SliderEventType.ARROW_UP -> SliderState.IDLE
+ SliderEventType.STOPPED_TRACKING_PROGRAM -> SliderState.IDLE
else -> SliderState.ARROW_HANDLE_MOVED_ONCE
}
setState(nextState)
@@ -237,7 +238,7 @@
val reachedBookend = bookendReached(currentProgress)
val nextState =
when (newEventType) {
- SliderEventType.ARROW_UP -> SliderState.IDLE
+ SliderEventType.STOPPED_TRACKING_PROGRAM -> SliderState.IDLE
SliderEventType.STARTED_TRACKING_TOUCH -> {
// Launching the timer and going to WAIT
timerJob = launchTimer()
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperActivity.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperActivity.kt
new file mode 100644
index 0000000..692fbb0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ShortcutHelperActivity.kt
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2024 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.keyboard.shortcut
+
+import android.graphics.Insets
+import android.os.Bundle
+import android.view.View
+import android.view.WindowInsets
+import androidx.activity.BackEventCompat
+import androidx.activity.ComponentActivity
+import androidx.activity.OnBackPressedCallback
+import androidx.core.view.updatePadding
+import com.android.systemui.res.R
+import com.google.android.material.bottomsheet.BottomSheetBehavior
+import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
+import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HIDDEN
+
+/**
+ * Activity that hosts the new version of the keyboard shortcut helper. It will be used both for
+ * small and large screen devices.
+ */
+class ShortcutHelperActivity : ComponentActivity() {
+
+ private val bottomSheetContainer
+ get() = requireViewById<View>(R.id.shortcut_helper_sheet_container)
+
+ private val bottomSheet
+ get() = requireViewById<View>(R.id.shortcut_helper_sheet)
+
+ private val bottomSheetBehavior
+ get() = BottomSheetBehavior.from(bottomSheet)
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ setupEdgeToEdge()
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_keyboard_shortcut_helper)
+ setUpBottomSheetWidth()
+ setUpInsets()
+ setUpPredictiveBack()
+ setUpSheetDismissListener()
+ setUpDismissOnTouchOutside()
+ }
+
+ private fun setupEdgeToEdge() {
+ // Draw behind system bars
+ window.setDecorFitsSystemWindows(false)
+ }
+
+ private fun setUpBottomSheetWidth() {
+ val sheetScreenWidthFraction =
+ resources.getFloat(R.dimen.shortcut_helper_screen_width_fraction)
+ // maxWidth needs to be set before the sheet is drawn, otherwise the call will have no
+ // effect.
+ val screenWidth = resources.displayMetrics.widthPixels
+ bottomSheetBehavior.maxWidth = (sheetScreenWidthFraction * screenWidth).toInt()
+ }
+
+ private fun setUpInsets() {
+ bottomSheetContainer.setOnApplyWindowInsetsListener { _, insets ->
+ val safeDrawingInsets = insets.safeDrawing
+ // Make sure the bottom sheet is not covered by the status bar.
+ bottomSheetContainer.updatePadding(top = safeDrawingInsets.top)
+ // Make sure the contents inside of the bottom sheet are not hidden by system bars, or
+ // cutouts.
+ bottomSheet.updatePadding(
+ left = safeDrawingInsets.left,
+ right = safeDrawingInsets.right,
+ bottom = safeDrawingInsets.bottom
+ )
+ // The bottom sheet has to be expanded only after setting up insets, otherwise there is
+ // a bug and it will not use full height.
+ expandBottomSheet()
+
+ // Return CONSUMED if you don't want want the window insets to keep passing
+ // down to descendant views.
+ WindowInsets.CONSUMED
+ }
+ }
+
+ private fun expandBottomSheet() {
+ bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED
+ bottomSheetBehavior.skipCollapsed = true
+ }
+
+ private fun setUpPredictiveBack() {
+ val onBackPressedCallback =
+ object : OnBackPressedCallback(/* enabled= */ true) {
+ override fun handleOnBackStarted(backEvent: BackEventCompat) {
+ bottomSheetBehavior.startBackProgress(backEvent)
+ }
+
+ override fun handleOnBackProgressed(backEvent: BackEventCompat) {
+ bottomSheetBehavior.updateBackProgress(backEvent)
+ }
+
+ override fun handleOnBackPressed() {
+ bottomSheetBehavior.handleBackInvoked()
+ }
+
+ override fun handleOnBackCancelled() {
+ bottomSheetBehavior.cancelBackProgress()
+ }
+ }
+ onBackPressedDispatcher.addCallback(
+ owner = this,
+ onBackPressedCallback = onBackPressedCallback
+ )
+ }
+
+ private fun setUpSheetDismissListener() {
+ bottomSheetBehavior.addBottomSheetCallback(
+ object : BottomSheetCallback() {
+ override fun onStateChanged(bottomSheet: View, newState: Int) {
+ if (newState == STATE_HIDDEN) {
+ finish()
+ }
+ }
+
+ override fun onSlide(bottomSheet: View, slideOffset: Float) {}
+ }
+ )
+ }
+
+ private fun setUpDismissOnTouchOutside() {
+ bottomSheetContainer.setOnClickListener { finish() }
+ }
+}
+
+private val WindowInsets.safeDrawing
+ get() =
+ getInsets(WindowInsets.Type.systemBars())
+ .union(getInsets(WindowInsets.Type.ime()))
+ .union(getInsets(WindowInsets.Type.displayCutout()))
+
+private fun Insets.union(insets: Insets): Insets = Insets.max(this, insets)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DozeInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DozeInteractor.kt
index af1802f..d04e4f1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DozeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DozeInteractor.kt
@@ -19,6 +19,10 @@
import android.graphics.Point
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.KeyguardRepository
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.scene.shared.model.Scenes
+import dagger.Lazy
import javax.inject.Inject
@SysUISingleton
@@ -26,7 +30,16 @@
@Inject
constructor(
private val keyguardRepository: KeyguardRepository,
+ // TODO(b/336364825) Remove Lazy when SceneContainerFlag is released -
+ // while the flag is off, creating this object too early results in a crash
+ private val sceneInteractor: Lazy<SceneInteractor>,
) {
+ fun canDozeFromCurrentScene(): Boolean {
+ if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) {
+ return false
+ }
+ return sceneInteractor.get().currentScene.value == Scenes.Lockscreen
+ }
fun setAodAvailable(value: Boolean) {
keyguardRepository.setAodAvailable(value)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
index 39aa615..e441017 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
@@ -27,7 +27,6 @@
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine
-import com.android.systemui.util.kotlin.sample as sampleUtil
import com.android.wm.shell.animation.Interpolators
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
@@ -157,12 +156,8 @@
}
}
)
- .sampleUtil(finishedKeyguardState)
- .collect { keyguardState ->
- if (keyguardState == KeyguardState.ALTERNATE_BOUNCER) {
- startTransitionTo(KeyguardState.GONE)
- }
- }
+ .filterRelevantKeyguardState()
+ .collect { startTransitionTo(KeyguardState.GONE) }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
index 2c869bf..69c2c78d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
@@ -124,18 +124,6 @@
}
}
- fun startToGlanceableHubTransition() {
- scope.launch {
- KeyguardWmStateRefactor.isUnexpectedlyInLegacyMode()
- if (
- transitionInteractor.startedKeyguardState.replayCache.last() ==
- KeyguardState.DREAMING
- ) {
- startTransitionTo(KeyguardState.GLANCEABLE_HUB)
- }
- }
- }
-
@OptIn(FlowPreview::class)
private fun listenForDreamingToOccluded() {
if (KeyguardWmStateRefactor.isEnabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 7224536..d191768 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -226,7 +226,7 @@
val ambientIndicationVisible: Flow<Boolean> = repository.ambientIndicationVisible.asStateFlow()
/** Whether the primary bouncer is showing or not. */
- val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerShow
+ @JvmField val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerShow
/** Whether the alternate bouncer is showing or not. */
val alternateBouncerShowing: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
index 92612b8..7d05539 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
@@ -87,6 +87,7 @@
}
/** Whether either of the bouncers are visible when we're FINISHED in the given state. */
+ @JvmStatic
fun isBouncerState(state: KeyguardState): Boolean {
return state == PRIMARY_BOUNCER || state == ALTERNATE_BOUNCER
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt
index 9a6dca3..76edda3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/SideFpsProgressBarViewBinder.kt
@@ -20,8 +20,6 @@
import android.graphics.Point
import com.android.systemui.CoreStartable
import com.android.systemui.Flags
-import com.android.systemui.biometrics.SideFpsController
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.ui.view.SideFpsProgressBar
@@ -38,7 +36,7 @@
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch
-private const val spfsProgressBarCommand = "sfps-progress-bar"
+private const val sfpsProgressBarCommand = "sfps-progress-bar"
@SysUISingleton
class SideFpsProgressBarViewBinder
@@ -47,8 +45,6 @@
private val viewModel: SideFpsProgressBarViewModel,
private val view: SideFpsProgressBar,
@Application private val applicationScope: CoroutineScope,
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- private val sfpsController: dagger.Lazy<SideFpsController>,
private val logger: SideFpsLogger,
private val commandRegistry: CommandRegistry,
) : CoreStartable {
@@ -61,7 +57,7 @@
// not required.
var layoutJob: Job? = null
var progressJob: Job? = null
- commandRegistry.registerCommand(spfsProgressBarCommand) { SfpsProgressBarCommand() }
+ commandRegistry.registerCommand(sfpsProgressBarCommand) { SfpsProgressBarCommand() }
applicationScope.launch {
viewModel.isProlongedTouchRequiredForAuthentication.collectLatest { enabled ->
logger.isProlongedTouchRequiredForAuthenticationChanged(enabled)
@@ -109,17 +105,6 @@
) {
logger.sfpsProgressBarStateChanged(visible, location, fpDetectRunning, length, rotation)
view.updateView(visible, location, length, thickness, rotation)
- // We have to hide the SFPS indicator as the progress bar will
- // be shown at the same location
- if (!SideFpsControllerRefactor.isEnabled) {
- if (visible) {
- logger.hidingSfpsIndicator()
- sfpsController.get().hideIndicator()
- } else if (fpDetectRunning) {
- logger.showingSfpsIndicator()
- sfpsController.get().showIndicator()
- }
- }
}
inner class SfpsProgressBarCommand : Command {
@@ -164,7 +149,7 @@
}
override fun help(pw: PrintWriter) {
- pw.println("Usage: adb shell cmd statusbar $spfsProgressBarCommand <command>")
+ pw.println("Usage: adb shell cmd statusbar $sfpsProgressBarCommand <command>")
pw.println("Available commands:")
pw.println(" show x y width height rotation")
pw.println(" hide")
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
index d948e47..7468675 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModel.kt
@@ -19,7 +19,6 @@
import com.android.app.animation.Interpolators.EMPHASIZED
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.res.R
@@ -38,10 +37,7 @@
constructor(
animationFlow: KeyguardTransitionAnimationFlow,
configurationInteractor: ConfigurationInteractor,
- private val fromDreamingTransitionInteractor: FromDreamingTransitionInteractor,
) {
- fun startTransition() = fromDreamingTransitionInteractor.startToGlanceableHubTransition()
-
private val transitionAnimation =
animationFlow.setup(
duration = TO_GLANCEABLE_HUB_DURATION,
diff --git a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
index 5dafd94..c997617 100644
--- a/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
+++ b/packages/SystemUI/src/com/android/systemui/lifecycle/RepeatWhenAttached.kt
@@ -17,6 +17,7 @@
package com.android.systemui.lifecycle
+import android.os.Trace
import android.view.View
import android.view.ViewTreeObserver
import androidx.annotation.MainThread
@@ -73,7 +74,7 @@
Dispatchers.Main + createCoroutineTracingContext() + coroutineContext
val traceName =
if (Compile.IS_DEBUG && coroutineTracing()) {
- traceSectionName()
+ inferTraceSectionName()
} else {
DEFAULT_TRACE_NAME
}
@@ -197,16 +198,21 @@
frame.className != CURRENT_CLASS_NAME && frame.className != JAVA_ADAPTER_CLASS_NAME
/** Get a name for the trace section include the name of the call site. */
-private fun traceSectionName(): String {
- val interestingFrame =
- StackWalker.getInstance().walk { stream ->
- stream.filter(::isFrameInteresting).limit(5).findFirst()
+private fun inferTraceSectionName(): String {
+ try {
+ Trace.traceBegin(Trace.TRACE_TAG_APP, "RepeatWhenAttachedKt#inferTraceSectionName")
+ val interestingFrame =
+ StackWalker.getInstance().walk { stream ->
+ stream.filter(::isFrameInteresting).limit(5).findFirst()
+ }
+ if (interestingFrame.isPresent) {
+ val f = interestingFrame.get()
+ return "${f.className}#${f.methodName}:${f.lineNumber} [$DEFAULT_TRACE_NAME]"
+ } else {
+ return DEFAULT_TRACE_NAME
}
- if (interestingFrame.isPresent) {
- val frame = interestingFrame.get()
- return "${frame.className}#${frame.methodName}:${frame.lineNumber} [$DEFAULT_TRACE_NAME]"
- } else {
- return DEFAULT_TRACE_NAME
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_APP)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
index bd3893b..e6c785e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
@@ -57,6 +57,7 @@
import android.media.session.PlaybackState;
import android.os.Process;
import android.os.Trace;
+import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
@@ -738,11 +739,11 @@
mPackageName, mMediaViewHolder.getSeamlessButton());
} else {
mLogger.logOpenOutputSwitcher(mUid, mPackageName, mInstanceId);
- // TODO: b/321969740 - Populate the userHandle parameter. The user
- // handle is necessary to disambiguate the same package running on
- // different users.
mMediaOutputDialogManager.createAndShow(
- mPackageName, true, mMediaViewHolder.getSeamlessButton(), null);
+ mPackageName,
+ /* aboveStatusBar */ true,
+ mMediaViewHolder.getSeamlessButton(),
+ UserHandle.getUserHandleForUid(mUid));
}
} else {
mLogger.logOpenOutputSwitcher(mUid, mPackageName, mInstanceId);
@@ -770,11 +771,11 @@
Log.w(TAG, "Device pending intent is not an activity.");
}
} else {
- // TODO: b/321969740 - Populate the userHandle parameter. The user
- // handle is necessary to disambiguate the same package running on
- // different users.
mMediaOutputDialogManager.createAndShow(
- mPackageName, true, mMediaViewHolder.getSeamlessButton(), null);
+ mPackageName,
+ /* aboveStatusBar */ true,
+ mMediaViewHolder.getSeamlessButton(),
+ UserHandle.getUserHandleForUid(mUid));
}
}
});
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 4ee2db7..042fb63f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -75,6 +75,10 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+ // set layer to make alpha animation of brightness slider nicer - otherwise elements
+ // of slider are animated separately and it doesn't look good. See b/329244723
+ setLayerType(LAYER_TYPE_HARDWARE, null);
+
mQSPanelContainer = findViewById(R.id.expanded_qs_scroll_view);
mQSPanel = findViewById(R.id.quick_settings_panel);
mHeader = findViewById(R.id.header);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
index b866dda..19b45d5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetAdapter.java
@@ -25,6 +25,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -37,8 +38,12 @@
import com.android.settingslib.Utils;
import com.android.settingslib.wifi.WifiUtils;
import com.android.systemui.res.R;
+import com.android.wifi.flags.Flags;
import com.android.wifitrackerlib.WifiEntry;
+import kotlinx.coroutines.CoroutineScope;
+import kotlinx.coroutines.Job;
+
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
@@ -50,6 +55,7 @@
private static final String TAG = "InternetAdapter";
private final InternetDialogController mInternetDialogController;
+ private final CoroutineScope mCoroutineScope;
@Nullable
private List<WifiEntry> mWifiEntries;
@VisibleForTesting
@@ -60,8 +66,9 @@
protected View mHolderView;
protected Context mContext;
- public InternetAdapter(InternetDialogController controller) {
+ public InternetAdapter(InternetDialogController controller, CoroutineScope coroutineScope) {
mInternetDialogController = controller;
+ mCoroutineScope = coroutineScope;
}
@Override
@@ -70,7 +77,7 @@
mContext = viewGroup.getContext();
mHolderView = LayoutInflater.from(mContext).inflate(R.layout.internet_list_item,
viewGroup, false);
- return new InternetViewHolder(mHolderView, mInternetDialogController);
+ return new InternetViewHolder(mHolderView, mInternetDialogController, mCoroutineScope);
}
@Override
@@ -131,11 +138,16 @@
final ImageView mWifiEndIcon;
final Context mContext;
final InternetDialogController mInternetDialogController;
+ final CoroutineScope mCoroutineScope;
+ @Nullable
+ private Job mJob;
- InternetViewHolder(View view, InternetDialogController internetDialogController) {
+ InternetViewHolder(View view, InternetDialogController internetDialogController,
+ CoroutineScope coroutineScope) {
super(view);
mContext = view.getContext();
mInternetDialogController = internetDialogController;
+ mCoroutineScope = coroutineScope;
mContainerLayout = view.requireViewById(R.id.internet_container);
mWifiListLayout = view.requireViewById(R.id.wifi_list);
mWifiNetworkLayout = view.requireViewById(R.id.wifi_network_layout);
@@ -176,6 +188,24 @@
}
void onWifiClick(@NonNull WifiEntry wifiEntry, @NonNull View view) {
+ if (Flags.androidVWifiApi() && wifiEntry.getSecurityTypes().contains(
+ WifiEntry.SECURITY_WEP)) {
+ if (mJob == null) {
+ mJob = WifiUtils.checkWepAllowed(mContext, mCoroutineScope, wifiEntry.getSsid(),
+ WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG, intent -> {
+ mInternetDialogController.startActivity(intent, view);
+ return null;
+ }, () -> {
+ wifiConnect(wifiEntry, view);
+ return null;
+ });
+ }
+ return;
+ }
+ wifiConnect(wifiEntry, view);
+ }
+
+ void wifiConnect(@NonNull WifiEntry wifiEntry, @NonNull View view) {
if (wifiEntry.shouldEditBeforeConnect()) {
final Intent intent = WifiUtils.getWifiDialogIntent(wifiEntry.getKey(),
true /* connectForCaller */);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index a531ee6..d5b05ef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -747,7 +747,7 @@
return summary;
}
- private void startActivity(Intent intent, View view) {
+ void startActivity(Intent intent, View view) {
ActivityTransitionAnimator.Controller controller =
mDialogTransitionAnimator.createActivityTransitionController(view);
@@ -1348,15 +1348,12 @@
mDefaultDataSubId = defaultDataSubId;
}
- boolean mayLaunchShareWifiSettings(WifiEntry wifiEntry) {
+ boolean mayLaunchShareWifiSettings(WifiEntry wifiEntry, View view) {
Intent intent = getConfiguratorQrCodeGeneratorIntentOrNull(wifiEntry);
if (intent == null) {
return false;
}
- if (mCallback != null) {
- mCallback.dismissDialog();
- }
- mActivityStarter.startActivity(intent, false /* dismissShade */);
+ startActivity(intent, view);
return true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java
index 52cf4ec..1a881b6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegate.java
@@ -68,13 +68,15 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.wifitrackerlib.WifiEntry;
-import java.util.List;
-import java.util.concurrent.Executor;
-
import dagger.assisted.Assisted;
import dagger.assisted.AssistedFactory;
import dagger.assisted.AssistedInject;
+import kotlinx.coroutines.CoroutineScope;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+
/**
* Dialog for showing mobile network, connected Wi-Fi network and Wi-Fi networks.
*/
@@ -165,7 +167,8 @@
InternetDialogDelegate create(
@Assisted(ABOVE_STATUS_BAR) boolean aboveStatusBar,
@Assisted(CAN_CONFIG_MOBILE_DATA) boolean canConfigMobileData,
- @Assisted(CAN_CONFIG_WIFI) boolean canConfigWifi);
+ @Assisted(CAN_CONFIG_WIFI) boolean canConfigWifi,
+ @Assisted CoroutineScope coroutineScope);
}
@AssistedInject
@@ -176,6 +179,7 @@
@Assisted(ABOVE_STATUS_BAR) boolean canConfigMobileData,
@Assisted(CAN_CONFIG_MOBILE_DATA) boolean canConfigWifi,
@Assisted(CAN_CONFIG_WIFI) boolean aboveStatusBar,
+ @Assisted CoroutineScope coroutineScope,
UiEventLogger uiEventLogger,
DialogTransitionAnimator dialogTransitionAnimator,
@Main Handler handler,
@@ -202,7 +206,7 @@
mUiEventLogger = uiEventLogger;
mDialogTransitionAnimator = dialogTransitionAnimator;
- mAdapter = new InternetAdapter(mInternetDialogController);
+ mAdapter = new InternetAdapter(mInternetDialogController, coroutineScope);
}
@Override
@@ -391,7 +395,7 @@
});
mDoneButton.setOnClickListener(v -> dialog.dismiss());
mShareWifiButton.setOnClickListener(v -> {
- if (mInternetDialogController.mayLaunchShareWifiSettings(mConnectedWifiEntry)) {
+ if (mInternetDialogController.mayLaunchShareWifiSettings(mConnectedWifiEntry, v)) {
mUiEventLogger.log(InternetDialogEvent.SHARE_WIFI_QS_BUTTON_CLICKED);
}
});
@@ -415,7 +419,7 @@
}
private void setMobileDataLayout(SystemUIDialog dialog, boolean activeNetworkIsCellular,
- boolean isCarrierNetworkActive) {
+ boolean isCarrierNetworkActive) {
boolean isNetworkConnected = activeNetworkIsCellular || isCarrierNetworkActive;
// 1. Mobile network should be gone if airplane mode ON or the list of active
// subscriptionId is null.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogManager.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogManager.kt
index 2a177c7..5aef950 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogManager.kt
@@ -21,26 +21,35 @@
import com.android.systemui.animation.DialogCuj
import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.statusbar.phone.SystemUIDialog
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.cancel
private const val TAG = "InternetDialogFactory"
private val DEBUG = Log.isLoggable(TAG, Log.DEBUG)
-/**
- * Factory to create [InternetDialogDelegate] objects.
- */
+/** Factory to create [InternetDialogDelegate] objects. */
@SysUISingleton
-class InternetDialogManager @Inject constructor(
+class InternetDialogManager
+@Inject
+constructor(
private val dialogTransitionAnimator: DialogTransitionAnimator,
- private val dialogFactory: InternetDialogDelegate.Factory
+ private val dialogFactory: InternetDialogDelegate.Factory,
+ @Background private val bgDispatcher: CoroutineDispatcher,
) {
+ private lateinit var coroutineScope: CoroutineScope
companion object {
private const val INTERACTION_JANK_TAG = "internet"
var dialog: SystemUIDialog? = null
}
- /** Creates a [InternetDialogDelegate]. The dialog will be animated from [view] if it is not null. */
+ /**
+ * Creates a [InternetDialogDelegate]. The dialog will be animated from [view] if it is not
+ * null.
+ */
fun create(
aboveStatusBar: Boolean,
canConfigMobileData: Boolean,
@@ -53,16 +62,21 @@
}
return
} else {
- dialog = dialogFactory.create(
- aboveStatusBar, canConfigMobileData, canConfigWifi).createDialog()
+ coroutineScope = CoroutineScope(bgDispatcher)
+ dialog =
+ dialogFactory
+ .create(aboveStatusBar, canConfigMobileData, canConfigWifi, coroutineScope)
+ .createDialog()
if (view != null) {
dialogTransitionAnimator.showFromView(
- dialog!!, view,
+ dialog!!,
+ view,
animateBackgroundBoundsChange = true,
- cuj = DialogCuj(
- InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
- INTERACTION_JANK_TAG
- )
+ cuj =
+ DialogCuj(
+ InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN,
+ INTERACTION_JANK_TAG
+ )
)
} else {
dialog!!.show()
@@ -74,6 +88,9 @@
if (DEBUG) {
Log.d(TAG, "destroyDialog")
}
+ if (dialog != null) {
+ coroutineScope.cancel()
+ }
dialog = null
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index ae2bb8b..4fc24b8 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -21,11 +21,13 @@
import android.app.StatusBarManager
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
+import com.android.internal.logging.UiEventLogger
import com.android.systemui.CoreStartable
import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
import com.android.systemui.bouncer.domain.interactor.SimBouncerInteractor
+import com.android.systemui.bouncer.shared.logging.BouncerUiEvent
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.classifier.FalsingCollectorActual
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
@@ -35,6 +37,7 @@
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor
+import com.android.systemui.deviceentry.shared.model.DeviceUnlockSource
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.model.SceneContainerPlugin
import com.android.systemui.model.SysUiState
@@ -107,6 +110,7 @@
private val occlusionInteractor: SceneContainerOcclusionInteractor,
private val faceUnlockInteractor: DeviceEntryFaceAuthInteractor,
private val shadeInteractor: ShadeInteractor,
+ private val uiEventLogger: UiEventLogger,
) : CoreStartable {
override fun start() {
@@ -282,6 +286,12 @@
}
}
+ if (
+ isOnBouncer &&
+ deviceUnlockStatus.deviceUnlockSource == DeviceUnlockSource.TrustAgent
+ ) {
+ uiEventLogger.log(BouncerUiEvent.BOUNCER_DISMISS_EXTENDED_ACCESS)
+ }
when {
isOnBouncer ->
// When the device becomes unlocked in Bouncer, go to previous scene,
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 13f508a..501a4a7 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -19,7 +19,7 @@
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
-import static com.android.systemui.Flags.screenshotShelfUi;
+import static com.android.systemui.Flags.screenshotShelfUi2;
import static com.android.systemui.screenshot.LogConfig.DEBUG_ANIM;
import static com.android.systemui.screenshot.LogConfig.DEBUG_CALLBACK;
import static com.android.systemui.screenshot.LogConfig.DEBUG_INPUT;
@@ -403,7 +403,7 @@
return;
}
- if (screenshotShelfUi()) {
+ if (screenshotShelfUi2()) {
final UUID requestId = UUID.randomUUID();
final String screenshotId = String.format("Screenshot_%s", requestId);
mActionsProvider = mActionsProviderFactory.create(
@@ -454,7 +454,7 @@
// ignore system bar insets for the purpose of window layout
mWindow.getDecorView().setOnApplyWindowInsetsListener(
(v, insets) -> WindowInsets.CONSUMED);
- if (!screenshotShelfUi()) {
+ if (!screenshotShelfUi2()) {
mScreenshotHandler.cancelTimeout(); // restarted after animation
}
}
@@ -503,7 +503,7 @@
}
boolean isPendingSharedTransition() {
- if (screenshotShelfUi()) {
+ if (screenshotShelfUi2()) {
return mActionExecutor.isPendingSharedTransition();
} else {
return mViewProxy.isPendingSharedTransition();
@@ -624,7 +624,7 @@
(response) -> {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_IMPRESSION,
0, response.getPackageName());
- if (screenshotShelfUi() && mActionsProvider != null) {
+ if (screenshotShelfUi2() && mActionsProvider != null) {
mActionsProvider.onScrollChipReady(
() -> onScrollButtonClicked(owner, response));
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
index 303eb78..12a3daa 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotShelfViewProxy.kt
@@ -31,6 +31,7 @@
import android.view.WindowManager
import android.window.OnBackInvokedCallback
import android.window.OnBackInvokedDispatcher
+import androidx.core.animation.doOnEnd
import com.android.internal.logging.UiEventLogger
import com.android.systemui.log.DebugLogger.debugLog
import com.android.systemui.res.R
@@ -109,7 +110,10 @@
override fun updateOrientation(insets: WindowInsets) {}
override fun createScreenshotDropInAnimation(screenRect: Rect, showFlash: Boolean): Animator {
- return animationController.getEntranceAnimation()
+ val entrance = animationController.getEntranceAnimation(screenRect, showFlash)
+ // reset the timeout when animation finishes
+ entrance.doOnEnd { callbacks?.onUserInteraction() }
+ return entrance
}
override fun addQuickShareChip(quickShareAction: Notification.Action) {}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
index ab23e5f..9b8d047 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
@@ -16,7 +16,7 @@
package com.android.systemui.screenshot.dagger;
-import static com.android.systemui.Flags.screenshotShelfUi;
+import static com.android.systemui.Flags.screenshotShelfUi2;
import android.app.Service;
import android.view.accessibility.AccessibilityManager;
@@ -99,7 +99,7 @@
static ScreenshotViewProxy.Factory providesScreenshotViewProxyFactory(
ScreenshotShelfViewProxy.Factory shelfScreenshotViewProxyFactory,
LegacyScreenshotViewProxy.Factory legacyScreenshotViewProxyFactory) {
- if (screenshotShelfUi()) {
+ if (screenshotShelfUi2()) {
return shelfScreenshotViewProxyFactory;
} else {
return legacyScreenshotViewProxyFactory;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt
index 9cf8ca5..3f4f74b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/ScreenshotAnimationController.kt
@@ -17,9 +17,16 @@
package com.android.systemui.screenshot.ui
import android.animation.Animator
-import android.animation.AnimatorListenerAdapter
+import android.animation.AnimatorSet
+import android.animation.ObjectAnimator
import android.animation.ValueAnimator
+import android.graphics.PointF
+import android.graphics.Rect
+import android.util.MathUtils
import android.view.View
+import android.view.animation.AnimationUtils
+import androidx.core.animation.doOnEnd
+import androidx.core.animation.doOnStart
import com.android.systemui.res.R
import kotlin.math.abs
import kotlin.math.max
@@ -27,23 +34,57 @@
class ScreenshotAnimationController(private val view: ScreenshotShelfView) {
private var animator: Animator? = null
+ private val screenshotPreview = view.requireViewById<View>(R.id.screenshot_preview)
+ private val flashView = view.requireViewById<View>(R.id.screenshot_flash)
private val actionContainer = view.requireViewById<View>(R.id.actions_container_background)
-
- fun getEntranceAnimation(): Animator {
- val animator = ValueAnimator.ofFloat(0f, 1f)
- animator.addUpdateListener { view.alpha = it.animatedFraction }
- animator.addListener(
- object : AnimatorListenerAdapter() {
- override fun onAnimationStart(animator: Animator) {
- view.alpha = 0f
- }
- override fun onAnimationEnd(animator: Animator) {
- view.alpha = 1f
- }
- }
+ private val fastOutSlowIn =
+ AnimationUtils.loadInterpolator(view.context, android.R.interpolator.fast_out_slow_in)
+ private val staticUI =
+ listOf<View>(
+ view.requireViewById(R.id.screenshot_preview_border),
+ view.requireViewById(R.id.actions_container_background),
+ view.requireViewById(R.id.screenshot_badge),
+ view.requireViewById(R.id.screenshot_dismiss_button)
)
- this.animator = animator
- return animator
+
+ fun getEntranceAnimation(bounds: Rect, showFlash: Boolean): Animator {
+ val entranceAnimation = AnimatorSet()
+
+ val previewAnimator = getPreviewAnimator(bounds)
+
+ if (showFlash) {
+ val flashInAnimator =
+ ObjectAnimator.ofFloat(flashView, "alpha", 0f, 1f).apply {
+ duration = FLASH_IN_DURATION_MS
+ interpolator = fastOutSlowIn
+ }
+ val flashOutAnimator =
+ ObjectAnimator.ofFloat(flashView, "alpha", 1f, 0f).apply {
+ duration = FLASH_OUT_DURATION_MS
+ interpolator = fastOutSlowIn
+ }
+ flashInAnimator.doOnStart { flashView.visibility = View.VISIBLE }
+ flashOutAnimator.doOnEnd { flashView.visibility = View.GONE }
+ entranceAnimation.play(flashOutAnimator).after(flashInAnimator)
+ entranceAnimation.play(previewAnimator).with(flashOutAnimator)
+ entranceAnimation.doOnStart { screenshotPreview.visibility = View.INVISIBLE }
+ }
+
+ val fadeInAnimator = ValueAnimator.ofFloat(0f, 1f)
+ fadeInAnimator.addUpdateListener {
+ for (child in staticUI) {
+ child.alpha = it.animatedValue as Float
+ }
+ }
+ entranceAnimation.play(fadeInAnimator).after(previewAnimator)
+ entranceAnimation.doOnStart {
+ for (child in staticUI) {
+ child.alpha = 0f
+ }
+ }
+
+ this.animator = entranceAnimation
+ return entranceAnimation
}
fun getSwipeReturnAnimation(): Animator {
@@ -81,11 +122,49 @@
animator?.cancel()
}
+ private fun getPreviewAnimator(bounds: Rect): Animator {
+ val targetPosition = Rect()
+ screenshotPreview.getHitRect(targetPosition)
+ val startXScale = bounds.width() / targetPosition.width().toFloat()
+ val startYScale = bounds.height() / targetPosition.height().toFloat()
+ val startPos = PointF(bounds.exactCenterX(), bounds.exactCenterY())
+ val endPos = PointF(targetPosition.exactCenterX(), targetPosition.exactCenterY())
+
+ val previewYAnimator =
+ ValueAnimator.ofFloat(startPos.y, endPos.y).apply {
+ duration = PREVIEW_Y_ANIMATION_DURATION_MS
+ interpolator = fastOutSlowIn
+ }
+ previewYAnimator.addUpdateListener {
+ val progress = it.animatedValue as Float
+ screenshotPreview.y = progress - screenshotPreview.height / 2f
+ }
+ // scale animation starts/finishes at the same time as x placement
+ val previewXAndScaleAnimator =
+ ValueAnimator.ofFloat(0f, 1f).apply {
+ duration = PREVIEW_X_ANIMATION_DURATION_MS
+ interpolator = fastOutSlowIn
+ }
+ previewXAndScaleAnimator.addUpdateListener {
+ val t = it.animatedFraction
+ screenshotPreview.scaleX = MathUtils.lerp(startXScale, 1f, t)
+ screenshotPreview.scaleY = MathUtils.lerp(startYScale, 1f, t)
+ screenshotPreview.x =
+ MathUtils.lerp(startPos.x, endPos.x, t) - screenshotPreview.width / 2f
+ }
+
+ val previewAnimator = AnimatorSet()
+ previewAnimator.play(previewXAndScaleAnimator).with(previewYAnimator)
+
+ previewAnimator.doOnStart { screenshotPreview.visibility = View.VISIBLE }
+ return previewAnimator
+ }
+
private fun getAdjustedVelocity(requestedVelocity: Float?): Float {
return if (requestedVelocity == null) {
val isLTR = view.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_LTR
// dismiss to the left in LTR locales, to the right in RTL
- if (isLTR) -1 * MINIMUM_VELOCITY else MINIMUM_VELOCITY
+ if (isLTR) -MINIMUM_VELOCITY else MINIMUM_VELOCITY
} else {
sign(requestedVelocity) * max(MINIMUM_VELOCITY, abs(requestedVelocity))
}
@@ -93,5 +172,9 @@
companion object {
private const val MINIMUM_VELOCITY = 1.5f // pixels per second
+ private const val FLASH_IN_DURATION_MS: Long = 133
+ private const val FLASH_OUT_DURATION_MS: Long = 217
+ private const val PREVIEW_X_ANIMATION_DURATION_MS: Long = 234
+ private const val PREVIEW_Y_ANIMATION_DURATION_MS: Long = 500
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/SwipeGestureListener.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/SwipeGestureListener.kt
index 7274757..61d4489 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/SwipeGestureListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/SwipeGestureListener.kt
@@ -24,7 +24,7 @@
class SwipeGestureListener(
private val view: View,
- private val onDismiss: (Float) -> Unit,
+ private val onDismiss: (Float?) -> Unit,
private val onCancel: () -> Unit
) {
private val velocityTracker = VelocityTracker.obtain()
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt
index 3e35295..3376b8c 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ui/binder/ScreenshotShelfViewBinder.kt
@@ -30,6 +30,7 @@
import com.android.systemui.screenshot.ui.SwipeGestureListener
import com.android.systemui.screenshot.ui.viewmodel.ScreenshotViewModel
import com.android.systemui.util.children
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
object ScreenshotShelfViewBinder {
@@ -60,7 +61,8 @@
onDismissalRequested(ScreenshotEvent.SCREENSHOT_EXPLICIT_DISMISSAL, null)
}
- view.repeatWhenAttached {
+ // use immediate dispatcher to ensure screenshot bitmap is set before animation
+ view.repeatWhenAttached(Dispatchers.Main.immediate) {
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
launch {
@@ -96,9 +98,9 @@
// ID is unique.
val newIds = visibleActions.map { it.id }
- for (view in actionsContainer.children.toList()) {
- if (view.tag !in newIds) {
- actionsContainer.removeView(view)
+ for (child in actionsContainer.children.toList()) {
+ if (child.tag !in newIds) {
+ actionsContainer.removeView(child)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index 8397d9f..37f2a21 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -47,7 +47,9 @@
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.android.systemui.Flags;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.settings.DisplayTracker;
@@ -370,10 +372,18 @@
mBackgroundHandler.post(new Runnable() {
@Override
public void run() {
- mControl.setEnforcedAdmin(
+ int userId = mUserTracker.getUserId();
+ RestrictedLockUtils.EnforcedAdmin enforcedAdmin =
RestrictedLockUtilsInternal.checkIfRestrictionEnforced(mContext,
UserManager.DISALLOW_CONFIG_BRIGHTNESS,
- mUserTracker.getUserId()));
+ userId);
+ if (Flags.enforceBrightnessBaseUserRestriction() && enforcedAdmin == null
+ && RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
+ UserManager.DISALLOW_CONFIG_BRIGHTNESS,
+ userId)) {
+ enforcedAdmin = new RestrictedLockUtils.EnforcedAdmin();
+ }
+ mControl.setEnforcedAdmin(enforcedAdmin);
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
index b425fb9..083cee7 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
@@ -33,7 +33,7 @@
import com.android.systemui.Gefingerpoken;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.haptics.slider.HapticSliderViewBinder;
-import com.android.systemui.haptics.slider.SeekableSliderHapticPlugin;
+import com.android.systemui.haptics.slider.SeekbarHapticPlugin;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.res.R;
@@ -65,7 +65,7 @@
private final FalsingManager mFalsingManager;
private final UiEventLogger mUiEventLogger;
- private final SeekableSliderHapticPlugin mBrightnessSliderHapticPlugin;
+ private final SeekbarHapticPlugin mBrightnessSliderHapticPlugin;
private final ActivityStarter mActivityStarter;
private final Gefingerpoken mOnInterceptListener = new Gefingerpoken() {
@@ -89,7 +89,7 @@
BrightnessSliderView brightnessSliderView,
FalsingManager falsingManager,
UiEventLogger uiEventLogger,
- SeekableSliderHapticPlugin brightnessSliderHapticPlugin,
+ SeekbarHapticPlugin brightnessSliderHapticPlugin,
ActivityStarter activityStarter) {
super(brightnessSliderView);
mFalsingManager = falsingManager;
@@ -314,7 +314,7 @@
int layout = getLayout();
BrightnessSliderView root = (BrightnessSliderView) LayoutInflater.from(context)
.inflate(layout, viewRoot, false);
- SeekableSliderHapticPlugin plugin = new SeekableSliderHapticPlugin(
+ SeekbarHapticPlugin plugin = new SeekbarHapticPlugin(
mVibratorHelper,
mSystemClock);
if (hapticBrightnessSlider()) {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
index 92006a4..e051dab 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
@@ -63,7 +63,6 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- setLayerType(LAYER_TYPE_HARDWARE, null);
mSlider = requireViewById(R.id.slider);
mSlider.setAccessibilityLabel(getContentDescription().toString());
diff --git a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
index a8481cd..a5a5474 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
@@ -28,10 +28,14 @@
import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
import androidx.compose.ui.platform.ComposeView
import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.LifecycleRegistry
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.android.compose.theme.PlatformTheme
import com.android.internal.annotations.VisibleForTesting
+import com.android.systemui.ambient.touch.TouchMonitor
+import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent
import com.android.systemui.communal.dagger.Communal
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.communal.ui.compose.CommunalContainer
@@ -45,6 +49,8 @@
import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.phone.SystemUIDialogFactory
+import com.android.systemui.util.kotlin.BooleanFlowOperators.and
+import com.android.systemui.util.kotlin.BooleanFlowOperators.not
import com.android.systemui.util.kotlin.BooleanFlowOperators.or
import com.android.systemui.util.kotlin.collectFlow
import javax.inject.Inject
@@ -67,12 +73,27 @@
private val shadeInteractor: ShadeInteractor,
private val powerManager: PowerManager,
private val communalColors: CommunalColors,
- @Communal private val dataSourceDelegator: SceneDataSourceDelegator,
-) {
+ private val ambientTouchComponentFactory: AmbientTouchComponent.Factory,
+ @Communal private val dataSourceDelegator: SceneDataSourceDelegator
+) : LifecycleOwner {
/** The container view for the hub. This will not be initialized until [initView] is called. */
private var communalContainerView: View? = null
/**
+ * This lifecycle is used to control when the [touchMonitor] listens to touches. The lifecycle
+ * should only be [Lifecycle.State.RESUMED] when the hub is showing and not covered by anything,
+ * such as the notification shade or bouncer.
+ */
+ private var lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(this)
+
+ /**
+ * This [TouchMonitor] listens for top and bottom swipe gestures globally when the hub is open.
+ * When a top or bottom swipe is detected, they will be intercepted and used to open the
+ * notification shade/bouncer.
+ */
+ private var touchMonitor: TouchMonitor? = null
+
+ /**
* The width of the area in which a right edge swipe can open the hub, in pixels. Read from
* resources when [initView] is called.
*/
@@ -80,20 +101,6 @@
private var rightEdgeSwipeRegionWidth: Int = 0
/**
- * The height of the area in which a top edge swipe while the hub is open will not intercept
- * touches, in pixels. This allows the top edge swipe to instead open the notification shade.
- * Read from resources when [initView] is called.
- */
- private var topEdgeSwipeRegionWidth: Int = 0
-
- /**
- * The height of the area in which a bottom edge swipe while the hub is open will not intercept
- * touches, in pixels. This allows the bottom edge swipe to instead open the bouncer. Read from
- * resources when [initView] is called.
- */
- private var bottomEdgeSwipeRegionWidth: Int = 0
-
- /**
* True if we are currently tracking a gesture for opening the hub that started in the edge
* swipe region.
*/
@@ -102,9 +109,6 @@
/** True if we are currently tracking a touch on the hub while it's open. */
private var isTrackingHubTouch = false
- /** True if we are tracking a top or bottom swipe gesture while the hub is open. */
- private var isTrackingHubGesture = false
-
/**
* True if the hub UI is fully open, meaning it should receive touch input.
*
@@ -121,9 +125,15 @@
private var anyBouncerShowing = false
/**
- * True if the shade is fully expanded, meaning the hub should not receive any touch input.
+ * True if the shade is fully expanded and the user is not interacting with it anymore, meaning
+ * the hub should not receive any touch input.
*
- * Tracks [ShadeInteractor.isAnyFullyExpanded].
+ * We need to not pause the touch handling lifecycle as soon as the shade opens because if the
+ * user swipes down, then back up without lifting their finger, the lifecycle will be paused
+ * then resumed, and resuming force-stops all active touch sessions. This means the shade will
+ * not receive the end of the gesture and will be stuck open.
+ *
+ * Based on [ShadeInteractor.isAnyFullyExpanded] and [ShadeInteractor.isUserInteracting].
*/
private var shadeShowing = false
@@ -132,8 +142,6 @@
* and just let the dream overlay's touch handling deal with them.
*
* Tracks [KeyguardInteractor.isDreaming].
- *
- * TODO(b/328838259): figure out a proper solution for touch handling above the lock screen too
*/
private var isDreaming = false
@@ -192,28 +200,45 @@
throw RuntimeException("Communal view has already been initialized")
}
+ if (touchMonitor == null) {
+ touchMonitor =
+ ambientTouchComponentFactory.create(this, HashSet()).getTouchMonitor().apply {
+ init()
+ }
+ }
+ lifecycleRegistry.currentState = Lifecycle.State.CREATED
+
communalContainerView = containerView
rightEdgeSwipeRegionWidth =
containerView.resources.getDimensionPixelSize(
R.dimen.communal_right_edge_swipe_region_width
)
- topEdgeSwipeRegionWidth =
- containerView.resources.getDimensionPixelSize(
- R.dimen.communal_top_edge_swipe_region_height
- )
- bottomEdgeSwipeRegionWidth =
- containerView.resources.getDimensionPixelSize(
- R.dimen.communal_bottom_edge_swipe_region_height
- )
collectFlow(
containerView,
keyguardTransitionInteractor.isFinishedInStateWhere(KeyguardState::isBouncerState),
- { anyBouncerShowing = it }
+ {
+ anyBouncerShowing = it
+ updateLifecycleState()
+ }
)
- collectFlow(containerView, communalInteractor.isCommunalShowing, { hubShowing = it })
- collectFlow(containerView, shadeInteractor.isAnyFullyExpanded, { shadeShowing = it })
+ collectFlow(
+ containerView,
+ communalInteractor.isCommunalShowing,
+ {
+ hubShowing = it
+ updateLifecycleState()
+ }
+ )
+ collectFlow(
+ containerView,
+ and(shadeInteractor.isAnyFullyExpanded, not(shadeInteractor.isUserInteracting)),
+ {
+ shadeShowing = it
+ updateLifecycleState()
+ }
+ )
collectFlow(containerView, keyguardInteractor.isDreaming, { isDreaming = it })
communalContainerView = containerView
@@ -221,10 +246,24 @@
return containerView
}
+ /**
+ * Updates the lifecycle stored by the [lifecycleRegistry] to control when the [touchMonitor]
+ * should listen for and intercept top and bottom swipes.
+ */
+ private fun updateLifecycleState() {
+ val shouldInterceptGestures = hubShowing && !(shadeShowing || anyBouncerShowing)
+ if (shouldInterceptGestures) {
+ lifecycleRegistry.currentState = Lifecycle.State.RESUMED
+ } else {
+ lifecycleRegistry.currentState = Lifecycle.State.STARTED
+ }
+ }
+
/** Removes the container view from its parent. */
fun disposeView() {
communalContainerView?.let {
(it.parent as ViewGroup).removeView(it)
+ lifecycleRegistry.currentState = Lifecycle.State.CREATED
communalContainerView = null
}
}
@@ -262,15 +301,7 @@
if (isDown && !hubOccluded) {
// Only intercept down events if the hub isn't occluded by the bouncer or
// notification shade.
- val y = ev.rawY
- val topSwipe: Boolean = y <= topEdgeSwipeRegionWidth
- val bottomSwipe = y >= view.height - bottomEdgeSwipeRegionWidth
-
- if (topSwipe || bottomSwipe) {
- isTrackingHubGesture = true
- } else {
- isTrackingHubTouch = true
- }
+ isTrackingHubTouch = true
}
if (isTrackingHubTouch) {
@@ -283,19 +314,6 @@
// gesture
// may return false from dispatchTouchEvent.
return true
- } else if (isTrackingHubGesture) {
- // Tracking a top or bottom swipe on the hub UI.
- if (isUp || isCancel) {
- isTrackingHubGesture = false
- }
-
- // If we're dreaming, intercept touches so the hub UI doesn't receive them, but
- // don't do anything so that the dream's touch handling takes care of opening
- // the bouncer or shade.
- //
- // If we're not dreaming, we don't intercept touches at the top/bottom edge so that
- // swipes can open the notification shade and bouncer.
- return isDreaming
}
return false
@@ -347,4 +365,7 @@
0
)
}
+
+ override val lifecycle: Lifecycle
+ get() = lifecycleRegistry
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index adcb14a..8b7e11c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -448,6 +448,9 @@
|| mScreenOffAnimationController.shouldIgnoreKeyguardTouches()) {
mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+ } else if (state.glanceableHubShowing) {
+ mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
+ mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
} else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
// Make sure to remove FLAG_ALT_FOCUSABLE_IM when keyguard needs input.
@@ -611,6 +614,7 @@
state.panelVisible,
state.shadeOrQsExpanded,
state.notificationShadeFocusable,
+ state.glanceableHubShowing,
state.bouncerShowing,
state.keyguardFadingAway,
state.keyguardGoingAway,
@@ -740,6 +744,12 @@
}
@Override
+ public void setGlanceableHubShowing(boolean showing) {
+ mCurrentState.glanceableHubShowing = showing;
+ apply(mCurrentState);
+ }
+
+ @Override
public void setBackdropShowing(boolean showing) {
mCurrentState.mediaBackdropShowing = showing;
apply(mCurrentState);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
index e0a98b3..6a4b52a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowState.kt
@@ -35,6 +35,7 @@
@JvmField var shadeOrQsExpanded: Boolean = false,
@JvmField var notificationShadeFocusable: Boolean = false,
@JvmField var bouncerShowing: Boolean = false,
+ @JvmField var glanceableHubShowing: Boolean = false,
@JvmField var keyguardFadingAway: Boolean = false,
@JvmField var keyguardGoingAway: Boolean = false,
@JvmField var qsExpanded: Boolean = false,
@@ -79,6 +80,7 @@
shadeOrQsExpanded.toString(),
notificationShadeFocusable.toString(),
bouncerShowing.toString(),
+ glanceableHubShowing.toString(),
keyguardFadingAway.toString(),
keyguardGoingAway.toString(),
qsExpanded.toString(),
@@ -119,6 +121,7 @@
panelVisible: Boolean,
panelExpanded: Boolean,
notificationShadeFocusable: Boolean,
+ glanceableHubShowing: Boolean,
bouncerShowing: Boolean,
keyguardFadingAway: Boolean,
keyguardGoingAway: Boolean,
@@ -149,6 +152,7 @@
this.panelVisible = panelVisible
this.shadeOrQsExpanded = panelExpanded
this.notificationShadeFocusable = notificationShadeFocusable
+ this.glanceableHubShowing = glanceableHubShowing
this.bouncerShowing = bouncerShowing
this.keyguardFadingAway = keyguardFadingAway
this.keyguardGoingAway = keyguardGoingAway
@@ -197,6 +201,7 @@
"panelVisible",
"panelExpanded",
"notificationShadeFocusable",
+ "glanceableHubShowing",
"bouncerShowing",
"keyguardFadingAway",
"keyguardGoingAway",
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
index 907cf5e..44f86da 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java
@@ -25,7 +25,6 @@
import android.app.StatusBarManager;
import android.util.Log;
import android.view.GestureDetector;
-import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
@@ -74,14 +73,14 @@
import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import com.android.systemui.util.time.SystemClock;
+import kotlinx.coroutines.ExperimentalCoroutinesApi;
+
import java.io.PrintWriter;
import java.util.Optional;
import java.util.function.Consumer;
import javax.inject.Inject;
-import kotlinx.coroutines.ExperimentalCoroutinesApi;
-
/**
* Controller for {@link NotificationShadeWindowView}.
*/
@@ -137,6 +136,11 @@
private final PanelExpansionInteractor mPanelExpansionInteractor;
private final ShadeExpansionStateManager mShadeExpansionStateManager;
+ /**
+ * If {@code true}, an external touch sent in {@link #handleExternalTouch(MotionEvent)} has been
+ * intercepted and all future touch events for the gesture should be processed by this view.
+ */
+ private boolean mExternalTouchIntercepted = false;
private boolean mIsTrackingBarGesture = false;
private boolean mIsOcclusionTransitionRunning = false;
private DisableSubpixelTextTransitionListener mDisableSubpixelTextTransitionListener;
@@ -253,11 +257,28 @@
}
/**
- * Handle a touch event while dreaming by forwarding the event to the content view.
+ * Handle a touch event while dreaming or on the hub by forwarding the event to the content
+ * view.
+ * <p>
+ * Since important logic for handling touches lives in the dispatch/intercept phases, we
+ * simulate going through all of these stages before sending onTouchEvent if intercepted.
+ *
* @param event The event to forward.
*/
- public void handleDreamTouch(MotionEvent event) {
- mView.dispatchTouchEvent(event);
+ public void handleExternalTouch(MotionEvent event) {
+ if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ mExternalTouchIntercepted = false;
+ }
+
+ if (!mView.dispatchTouchEvent(event)) {
+ return;
+ }
+ if (!mExternalTouchIntercepted) {
+ mExternalTouchIntercepted = mView.onInterceptTouchEvent(event);
+ }
+ if (mExternalTouchIntercepted) {
+ mView.onTouchEvent(event);
+ }
}
/** Inflates the {@link R.layout#status_bar_expanded} layout and sets it up. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
index e669556..707d59aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java
@@ -86,6 +86,9 @@
/** Sets the state of whether the bouncer is showing or not. */
default void setBouncerShowing(boolean showing) {}
+ /** Sets the state of whether the glanceable hub is showing or not. */
+ default void setGlanceableHubShowing(boolean showing) {}
+
/** Sets the state of whether the backdrop is showing or not. */
default void setBackdropShowing(boolean showing) {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
index 724b19c..e3c47a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
@@ -83,6 +83,10 @@
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.util.CarrierConfigTracker;
+import dalvik.annotation.optimization.NeverCompile;
+
+import kotlin.Unit;
+
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -97,9 +101,6 @@
import javax.inject.Inject;
-import dalvik.annotation.optimization.NeverCompile;
-import kotlin.Unit;
-
/** Platform implementation of the network controller. **/
@SysUISingleton
public class NetworkControllerImpl extends BroadcastReceiver
@@ -464,7 +465,10 @@
});
};
- mDemoModeController.addCallback(this);
+ // TODO(b/336357360): Until we can remove this class entirely, disable its handling of ALL
+ // demo mode commands, due to the fact that the mobile command handler has an infinite
+ // loop bug if you use any slot other than 1.
+ // mDemoModeController.addCallback(this);
mDumpManager.registerNormalDumpable(TAG, this);
}
@@ -1317,6 +1321,8 @@
int carrierId = TextUtils.isEmpty(carrierIdString) ? 0
: Integer.parseInt(carrierIdString);
// Ensure we have enough sim slots
+ // TODO(b/336357360): This is the origination of the infinite loop bug, for those
+ // following along at home.
List<SubscriptionInfo> subs = new ArrayList<>();
while (mMobileSignalControllers.size() <= slot) {
int nextSlot = mMobileSignalControllers.size();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
index 9bb860f..594c191 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
@@ -41,7 +41,6 @@
import com.android.systemui.shade.ShadeSurface;
import com.android.systemui.shade.ShadeSurfaceImpl;
import com.android.systemui.shade.carrier.ShadeCarrierGroupController;
-import com.android.systemui.startable.Dependencies;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationClickNotifier;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -53,7 +52,6 @@
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.CentralSurfacesImpl;
import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
@@ -70,8 +68,6 @@
import dagger.multibindings.ClassKey;
import dagger.multibindings.IntoMap;
-import java.util.Set;
-
import javax.inject.Provider;
/**
@@ -161,15 +157,6 @@
CoreStartable bindsStartStatusBarStateController(StatusBarStateControllerImpl sbsc);
/** */
- @Provides
- @IntoMap
- @Dependencies
- @ClassKey(SysuiStatusBarStateController.class)
- static Set<Class<? extends CoreStartable>> providesStatusBarStateControllerDeps() {
- return Set.of(CentralSurfaces.class);
- }
-
- /** */
@Binds
StatusBarIconController provideStatusBarIconController(
StatusBarIconControllerImpl controllerImpl);
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 30e78b1..de0f247 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
@@ -4390,7 +4390,8 @@
/**
* See {@link AmbientState#setDozing}.
*/
- public void setDozing(boolean dozing, boolean animate) {
+ @Override
+ public void setDozing(boolean dozing) {
if (mAmbientState.isDozing() == dozing) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index d8a16ce..9ed5ac9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -98,6 +98,7 @@
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.LaunchAnimationParameters;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -166,6 +167,7 @@
private final NotificationGutsManager mNotificationGutsManager;
private final NotificationsController mNotificationsController;
private final NotificationVisibilityProvider mVisibilityProvider;
+ private final NotificationWakeUpCoordinator mWakeUpCoordinator;
private final HeadsUpManager mHeadsUpManager;
private final NotificationRoundnessManager mNotificationRoundnessManager;
private final TunerService mTunerService;
@@ -701,6 +703,7 @@
NotificationGutsManager notificationGutsManager,
NotificationsController notificationsController,
NotificationVisibilityProvider visibilityProvider,
+ NotificationWakeUpCoordinator wakeUpCoordinator,
HeadsUpManager headsUpManager,
NotificationRoundnessManager notificationRoundnessManager,
TunerService tunerService,
@@ -752,6 +755,7 @@
mNotificationGutsManager = notificationGutsManager;
mNotificationsController = notificationsController;
mVisibilityProvider = visibilityProvider;
+ mWakeUpCoordinator = wakeUpCoordinator;
mHeadsUpManager = headsUpManager;
mNotificationRoundnessManager = notificationRoundnessManager;
mTunerService = tunerService;
@@ -790,6 +794,9 @@
mActivityStarter = activityStarter;
mSensitiveNotificationProtectionController = sensitiveNotificationProtectionController;
mView.passSplitShadeStateController(splitShadeStateController);
+ if (SceneContainerFlag.isEnabled()) {
+ mWakeUpCoordinator.setStackScroller(this);
+ }
mDumpManager.registerDumpable(this);
updateResources();
setUpView();
@@ -1479,7 +1486,8 @@
}
public void setDozing(boolean dozing, boolean animate) {
- mView.setDozing(dozing, animate);
+ SceneContainerFlag.assertInLegacyMode();
+ mView.setDozing(dozing);
}
public void setPulsing(boolean pulsing, boolean animatePulse) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt
index ac00d3b..f356578 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/view/NotificationScrollView.kt
@@ -58,4 +58,7 @@
/** sets the current expand fraction */
fun setExpandFraction(expandFraction: Float)
+
+ /** Sets whether the view is displayed in doze mode. */
+ fun setDozing(dozing: Boolean)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt
index 047b560..2f9c2f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt
@@ -84,6 +84,7 @@
launch { viewModel.headsUpTop.collect { view.setHeadsUpTop(it) } }
launch { viewModel.expandFraction.collect { view.setExpandFraction(it) } }
launch { viewModel.isScrollable.collect { view.setScrollingEnabled(it) } }
+ launch { viewModel.isDozing.collect { isDozing -> view.setDozing(isDozing) } }
launchAndDispose {
view.setSyntheticScrollConsumer(viewModel.syntheticScrollConsumer)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
index 4ae5e69..7aeff71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt
@@ -20,7 +20,9 @@
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.notification.stack.domain.interactor.NotificationStackAppearanceInteractor
@@ -29,11 +31,13 @@
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_DELAYED_STACK_FADE_IN
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationTransitionThresholds.EXPANSION_FOR_MAX_SCRIM_ALPHA
import com.android.systemui.util.kotlin.FlowDumperImpl
-import javax.inject.Inject
+import dagger.Lazy
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
+import javax.inject.Inject
/** ViewModel which represents the state of the NSSL/Controller in the world of flexiglass */
@SysUISingleton
@@ -44,6 +48,9 @@
stackAppearanceInteractor: NotificationStackAppearanceInteractor,
shadeInteractor: ShadeInteractor,
sceneInteractor: SceneInteractor,
+ // TODO(b/336364825) Remove Lazy when SceneContainerFlag is released -
+ // while the flag is off, creating this object too early results in a crash
+ keyguardInteractor: Lazy<KeyguardInteractor>,
) : FlowDumperImpl(dumpManager) {
/**
* The expansion fraction of the notification stack. It should go from 0 to 1 when transitioning
@@ -138,4 +145,13 @@
/** Whether the notification stack is scrollable or not. */
val isScrollable: Flow<Boolean> =
sceneInteractor.currentScene.map { it == Scenes.Shade }.dumpWhileCollecting("isScrollable")
+
+ /** Whether the notification stack is displayed in doze mode. */
+ val isDozing: Flow<Boolean> by lazy {
+ if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) {
+ flowOf(false)
+ } else {
+ keyguardInteractor.get().isDozing.dumpWhileCollecting("isDozing")
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index 8fb552f..7d97428 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -283,11 +283,12 @@
void awakenDreams();
/**
- * Handle a touch event while dreaming when the touch was initiated within a prescribed
- * swipeable area. This method is provided for cases where swiping in certain areas of a dream
- * should be handled by CentralSurfaces instead (e.g. swiping communal hub open).
+ * Handle a touch event while dreaming or on the glanceable hub when the touch was initiated
+ * within a prescribed swipeable area. This method is provided for cases where swiping in
+ * certain areas should be handled by CentralSurfaces instead (e.g. swiping hub open, opening
+ * the notification shade over dream or hub).
*/
- void handleDreamTouch(MotionEvent event);
+ void handleExternalShadeWindowTouch(MotionEvent event);
boolean isBouncerShowing();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt
index 8af7ee8..d5e66ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt
@@ -79,7 +79,7 @@
override fun updateScrimController() {}
override fun shouldIgnoreTouch() = false
override fun isDeviceInteractive() = false
- override fun handleDreamTouch(event: MotionEvent?) {}
+ override fun handleExternalShadeWindowTouch(event: MotionEvent?) {}
override fun awakenDreams() {}
override fun isBouncerShowing() = false
override fun isBouncerShowingScrimmed() = false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index e9aa7aa..b2b2cea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -2928,8 +2928,8 @@
};
@Override
- public void handleDreamTouch(MotionEvent event) {
- getNotificationShadeWindowViewController().handleDreamTouch(event);
+ public void handleExternalShadeWindowTouch(MotionEvent event) {
+ getNotificationShadeWindowViewController().handleExternalTouch(event);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
index 7abcf13..033659b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java
@@ -37,9 +37,9 @@
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.doze.DozeReceiver;
-import com.android.systemui.flags.FeatureFlagsClassic;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.keyguard.domain.interactor.DozeInteractor;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.shade.NotificationShadeWindowViewController;
import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractor;
import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -84,7 +84,6 @@
private final SysuiStatusBarStateController mStatusBarStateController;
private final DeviceProvisionedController mDeviceProvisionedController;
private final HeadsUpManager mHeadsUpManager;
- private final FeatureFlagsClassic mFeatureFlags;
private final BatteryController mBatteryController;
private final ScrimController mScrimController;
private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
@@ -110,7 +109,6 @@
WakefulnessLifecycle wakefulnessLifecycle,
SysuiStatusBarStateController statusBarStateController,
DeviceProvisionedController deviceProvisionedController,
- FeatureFlagsClassic featureFlags,
HeadsUpManager headsUpManager, BatteryController batteryController,
ScrimController scrimController,
Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
@@ -135,7 +133,6 @@
mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
mAssistManagerLazy = assistManagerLazy;
mDozeScrimController = dozeScrimController;
- mFeatureFlags = featureFlags;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mPulseExpansionHandler = pulseExpansionHandler;
mNotificationShadeWindowController = notificationShadeWindowController;
@@ -236,8 +233,14 @@
void updateDozing() {
Assert.isMainThread();
- boolean dozing =
- mDozingRequested && mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
+ boolean dozing;
+ if (SceneContainerFlag.isEnabled()) {
+ dozing = mDozingRequested && mDozeInteractor.canDozeFromCurrentScene();
+ } else {
+ dozing = mDozingRequested
+ && mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
+ }
+
// When in wake-and-unlock we may not have received a change to StatusBarState
// but we still should not be dozing, manually set to false.
if (mBiometricUnlockControllerLazy.get().getMode()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
index 4129b3a..b80ff38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
@@ -42,6 +42,8 @@
import com.android.systemui.statusbar.pipeline.mobile.util.SubscriptionManagerProxyImpl
import com.android.systemui.statusbar.pipeline.satellite.data.DeviceBasedSatelliteRepository
import com.android.systemui.statusbar.pipeline.satellite.data.prod.DeviceBasedSatelliteRepositoryImpl
+import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModel
+import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.DeviceBasedSatelliteViewModelImpl
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl
import com.android.systemui.statusbar.pipeline.shared.ui.binder.CollapsedStatusBarViewBinder
@@ -85,6 +87,11 @@
impl: DeviceBasedSatelliteRepositoryImpl
): DeviceBasedSatelliteRepository
+ @Binds
+ abstract fun deviceBasedSatelliteViewModel(
+ impl: DeviceBasedSatelliteViewModelImpl
+ ): DeviceBasedSatelliteViewModel
+
@Binds abstract fun wifiRepository(impl: WifiRepositorySwitcher): WifiRepository
@Binds abstract fun wifiInteractor(impl: WifiInteractorImpl): WifiInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt
index a0291b8..f2255f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModel.kt
@@ -16,13 +16,16 @@
package com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel
+import android.content.Context
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
+import com.android.systemui.res.R
import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository
import com.android.systemui.statusbar.pipeline.dagger.OemSatelliteInputLog
import com.android.systemui.statusbar.pipeline.satellite.domain.interactor.DeviceBasedSatelliteInteractor
+import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState
import com.android.systemui.statusbar.pipeline.satellite.ui.model.SatelliteIconModel
import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds
@@ -42,15 +45,30 @@
* View-Model for the device-based satellite icon. This icon will only show in the status bar if
* satellite is available AND all other service states are considered OOS.
*/
+interface DeviceBasedSatelliteViewModel {
+ /**
+ * The satellite icon that should be displayed, or null if no satellite icon should be
+ * displayed.
+ */
+ val icon: StateFlow<Icon?>
+
+ /**
+ * The satellite-related text that should be used as the carrier text string when satellite is
+ * active, or null if the carrier text string shouldn't include any satellite information.
+ */
+ val carrierText: StateFlow<String?>
+}
+
@OptIn(ExperimentalCoroutinesApi::class)
-class DeviceBasedSatelliteViewModel
+class DeviceBasedSatelliteViewModelImpl
@Inject
constructor(
+ context: Context,
interactor: DeviceBasedSatelliteInteractor,
@Application scope: CoroutineScope,
airplaneModeRepository: AirplaneModeRepository,
@OemSatelliteInputLog logBuffer: LogBuffer,
-) {
+) : DeviceBasedSatelliteViewModel {
private val shouldShowIcon: Flow<Boolean> =
interactor.areAllConnectionsOutOfService.flatMapLatest { allOos ->
if (!allOos) {
@@ -87,7 +105,7 @@
}
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
- val icon: StateFlow<Icon?> =
+ override val icon: StateFlow<Icon?> =
combine(
shouldActuallyShowIcon,
interactor.connectionState,
@@ -101,6 +119,26 @@
}
.stateIn(scope, SharingStarted.WhileSubscribed(), null)
+ override val carrierText: StateFlow<String?> =
+ combine(
+ shouldActuallyShowIcon,
+ interactor.connectionState,
+ ) { shouldShow, connectionState ->
+ if (shouldShow) {
+ when (connectionState) {
+ SatelliteConnectionState.Connected ->
+ context.getString(R.string.satellite_connected_carrier_text)
+ SatelliteConnectionState.On ->
+ context.getString(R.string.satellite_not_connected_carrier_text)
+ SatelliteConnectionState.Off,
+ SatelliteConnectionState.Unknown -> null
+ }
+ } else {
+ null
+ }
+ }
+ .stateIn(scope, SharingStarted.WhileSubscribed(), null)
+
companion object {
private const val TAG = "DeviceBasedSatelliteViewModel"
private val DELAY_DURATION = 10.seconds
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
index b98eff8..615cc74 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
@@ -51,7 +51,7 @@
public class FlashlightControllerImpl implements FlashlightController {
private static final String TAG = "FlashlightController";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean DEBUG = true;
private static final int DISPATCH_ERROR = 0;
private static final int DISPATCH_CHANGED = 1;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 2245541..cd82e1d 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -118,7 +118,7 @@
import com.android.systemui.Prefs;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.haptics.slider.HapticSliderViewBinder;
-import com.android.systemui.haptics.slider.SeekableSliderHapticPlugin;
+import com.android.systemui.haptics.slider.SeekbarHapticPlugin;
import com.android.systemui.haptics.slider.SliderHapticFeedbackConfig;
import com.android.systemui.media.dialog.MediaOutputDialogManager;
import com.android.systemui.plugins.VolumeDialog;
@@ -2640,7 +2640,7 @@
private ObjectAnimator anim; // slider progress animation for non-touch-related updates
private int animTargetProgress;
private int lastAudibleLevel = 1;
- private SeekableSliderHapticPlugin mHapticPlugin;
+ private SeekbarHapticPlugin mHapticPlugin;
private int mProgressHapticsType = PROGRESS_HAPTICS_DISABLED;
void setIcon(int iconRes, Resources.Theme theme) {
@@ -2658,7 +2658,7 @@
com.android.systemui.util.time.SystemClock systemClock) {
if (mHapticPlugin != null) return;
- mHapticPlugin = new SeekableSliderHapticPlugin(
+ mHapticPlugin = new SeekbarHapticPlugin(
vibratorHelper,
systemClock,
sSliderHapticFeedbackConfig);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
new file mode 100644
index 0000000..ed44699
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2024 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.volume.domain.interactor
+
+import android.bluetooth.BluetoothAdapter
+import android.media.AudioDeviceInfo
+import android.media.AudioDeviceInfo.TYPE_WIRED_HEADPHONES
+import android.media.AudioDeviceInfo.TYPE_WIRED_HEADSET
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+import com.android.settingslib.media.BluetoothMediaDevice
+import com.android.settingslib.media.MediaDevice
+import com.android.settingslib.media.MediaDevice.MediaDeviceType
+import com.android.settingslib.volume.data.repository.AudioRepository
+import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.volume.domain.model.AudioOutputDevice
+import com.android.systemui.volume.panel.component.mediaoutput.data.repository.LocalMediaRepositoryFactory
+import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
+import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import javax.inject.Inject
+import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+
+/** Provides a currently active audio device data. */
+@VolumePanelScope
+@OptIn(ExperimentalCoroutinesApi::class)
+class AudioOutputInteractor
+@Inject
+constructor(
+ audioRepository: AudioRepository,
+ audioModeInteractor: AudioModeInteractor,
+ @VolumePanelScope scope: CoroutineScope,
+ @Background backgroundCoroutineContext: CoroutineContext,
+ private val localBluetoothManager: LocalBluetoothManager?,
+ private val bluetoothAdapter: BluetoothAdapter?,
+ private val deviceIconInteractor: DeviceIconInteractor,
+ private val mediaOutputInteractor: MediaOutputInteractor,
+ private val localMediaRepositoryFactory: LocalMediaRepositoryFactory,
+) {
+
+ val currentAudioDevice: Flow<AudioOutputDevice> =
+ audioModeInteractor.isOngoingCall
+ .flatMapLatest { isOngoingCall ->
+ if (isOngoingCall) {
+ audioRepository.communicationDevice.map { communicationDevice ->
+ communicationDevice?.toAudioOutputDevice()
+ }
+ } else {
+ mediaOutputInteractor.defaultActiveMediaSession
+ .flatMapLatest {
+ localMediaRepositoryFactory
+ .create(it?.packageName)
+ .currentConnectedDevice
+ }
+ .map { mediaDevice -> mediaDevice?.toAudioOutputDevice() }
+ }
+ }
+ .map { it ?: AudioOutputDevice.Unknown }
+ .flowOn(backgroundCoroutineContext)
+ .stateIn(scope, SharingStarted.Eagerly, AudioOutputDevice.Unknown)
+
+ private fun AudioDeviceInfo.toAudioOutputDevice(): AudioOutputDevice {
+ if (type == TYPE_WIRED_HEADPHONES || type == TYPE_WIRED_HEADSET) {
+ return AudioOutputDevice.Wired(
+ name = productName.toString(),
+ icon = deviceIconInteractor.loadIcon(type),
+ )
+ }
+ val cachedBluetoothDevice: CachedBluetoothDevice? =
+ if (address.isEmpty() || localBluetoothManager == null || bluetoothAdapter == null) {
+ null
+ } else {
+ val remoteDevice = bluetoothAdapter.getRemoteDevice(address)
+ localBluetoothManager.cachedDeviceManager.findDevice(remoteDevice)
+ }
+ return cachedBluetoothDevice?.let {
+ AudioOutputDevice.Bluetooth(
+ name = it.name,
+ icon = deviceIconInteractor.loadIcon(it),
+ cachedBluetoothDevice = it,
+ )
+ }
+ ?: AudioOutputDevice.BuiltIn(
+ name = productName.toString(),
+ icon = deviceIconInteractor.loadIcon(type),
+ )
+ }
+
+ private fun MediaDevice.toAudioOutputDevice(): AudioOutputDevice {
+ return when {
+ this is BluetoothMediaDevice ->
+ AudioOutputDevice.Bluetooth(
+ name = name,
+ icon = icon,
+ cachedBluetoothDevice = cachedDevice,
+ )
+ deviceType == MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE ->
+ AudioOutputDevice.Wired(
+ name = name,
+ icon = icon,
+ )
+ else ->
+ AudioOutputDevice.BuiltIn(
+ name = name,
+ icon = icon,
+ )
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/DeviceIconInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/DeviceIconInteractor.kt
new file mode 100644
index 0000000..a2f7d4a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/DeviceIconInteractor.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 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.volume.domain.interactor
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.graphics.drawable.Drawable
+import android.media.AudioDeviceInfo
+import com.android.settingslib.R
+import com.android.settingslib.bluetooth.BluetoothUtils
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.media.DeviceIconUtil
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
+import javax.inject.Inject
+
+/** Utility class to load an icon for a [CachedBluetoothDevice]. */
+@VolumePanelScope
+@SuppressLint("UseCompatLoadingForDrawables")
+class DeviceIconInteractor @Inject constructor(@Application private val context: Context) {
+
+ private val iconUtil: DeviceIconUtil = DeviceIconUtil(context)
+
+ fun loadIcon(@AudioDeviceInfo.AudioDeviceType type: Int): Drawable? =
+ context.getDrawable(iconUtil.getIconResIdFromAudioDeviceType(type))
+
+ fun loadIcon(cachedDevice: CachedBluetoothDevice): Drawable? {
+ return if (BluetoothUtils.isAdvancedUntetheredDevice(cachedDevice.device))
+ context.getDrawable(R.drawable.ic_earbuds_advanced)
+ else BluetoothUtils.getBtClassDrawableWithDescription(context, cachedDevice).first
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/model/AudioOutputDevice.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/model/AudioOutputDevice.kt
new file mode 100644
index 0000000..ba0b082
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/domain/model/AudioOutputDevice.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2024 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.volume.domain.model
+
+import android.graphics.drawable.Drawable
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+
+/** Models an audio output device. */
+sealed interface AudioOutputDevice {
+
+ val name: String
+ val icon: Drawable?
+
+ /** Models a built audio output device. */
+ data class BuiltIn(
+ override val name: String,
+ override val icon: Drawable?,
+ ) : AudioOutputDevice
+
+ /** Models a wired audio output device. */
+ data class Wired(
+ override val name: String,
+ override val icon: Drawable?,
+ ) : AudioOutputDevice
+
+ /** Models a bluetooth audio output device. */
+ data class Bluetooth(
+ override val name: String,
+ override val icon: Drawable?,
+ val cachedBluetoothDevice: CachedBluetoothDevice,
+ ) : AudioOutputDevice
+
+ /** Models a state when the current audio output device is unknown. */
+ data object Unknown : AudioOutputDevice {
+ override val name: String
+ get() = error("Unsupported for unknown device")
+
+ override val icon: Drawable
+ get() = error("Unsupported for unknown device")
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputActionsInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputActionsInteractor.kt
index eebb6fb..22c0530 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputActionsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputActionsInteractor.kt
@@ -21,7 +21,7 @@
import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.animation.Expandable
import com.android.systemui.media.dialog.MediaOutputDialogManager
-import com.android.systemui.volume.panel.component.mediaoutput.shared.model.SessionWithPlayback
+import com.android.systemui.volume.panel.component.mediaoutput.shared.model.SessionWithPlaybackState
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
import javax.inject.Inject
@@ -33,10 +33,10 @@
private val mediaOutputDialogManager: MediaOutputDialogManager,
) {
- fun onBarClick(sessionWithPlayback: SessionWithPlayback?, expandable: Expandable) {
- if (sessionWithPlayback?.playback?.isActive == true) {
+ fun onBarClick(sessionWithPlaybackState: SessionWithPlaybackState?, expandable: Expandable) {
+ if (sessionWithPlaybackState?.isPlaybackActive == true) {
mediaOutputDialogManager.createAndShowWithController(
- sessionWithPlayback.session.packageName,
+ sessionWithPlaybackState.session.packageName,
false,
expandable.dialogController()
)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
index 41ad035..83b8029 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
@@ -94,7 +94,7 @@
/** Currently connected [MediaDevice]. */
val currentConnectedDevice: Flow<MediaDevice?> =
- localMediaRepository.flatMapLatest { it.currentConnectedDevice }
+ localMediaRepository.flatMapLatest { it.currentConnectedDevice }.distinctUntilChanged()
private suspend fun getApplicationLabel(packageName: String): CharSequence? {
return try {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlaybackState.kt
similarity index 86%
rename from packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
rename to packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlaybackState.kt
index c4476fc..bac969d 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlaybackState.kt
@@ -16,9 +16,7 @@
package com.android.systemui.volume.panel.component.mediaoutput.shared.model
-import android.media.session.PlaybackState
-
-data class SessionWithPlayback(
+data class SessionWithPlaybackState(
val session: MediaDeviceSession,
- val playback: PlaybackState,
+ val isPlaybackActive: Boolean,
)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
index f19fa20..d60d981 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt
@@ -25,7 +25,7 @@
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputActionsInteractor
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
-import com.android.systemui.volume.panel.component.mediaoutput.shared.model.SessionWithPlayback
+import com.android.systemui.volume.panel.component.mediaoutput.shared.model.SessionWithPlaybackState
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
import com.android.systemui.volume.panel.shared.model.Result
import com.android.systemui.volume.panel.ui.VolumePanelUiEvent
@@ -35,10 +35,9 @@
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.stateIn
/** Models the UI of the Media Output Volume Panel component. */
@@ -55,20 +54,19 @@
private val uiEventLogger: UiEventLogger,
) {
- private val sessionWithPlayback: StateFlow<Result<SessionWithPlayback?>> =
+ private val sessionWithPlaybackState: StateFlow<Result<SessionWithPlaybackState?>> =
interactor.defaultActiveMediaSession
.flatMapLatest { session ->
if (session == null) {
- flowOf(Result.Data<SessionWithPlayback?>(null))
+ flowOf(Result.Data<SessionWithPlaybackState?>(null))
} else {
- mediaDeviceSessionInteractor
- .playbackState(session)
- .map { playback ->
- playback?.let {
- Result.Data<SessionWithPlayback?>(SessionWithPlayback(session, it))
- }
+ mediaDeviceSessionInteractor.playbackState(session).mapNotNull { playback ->
+ playback?.let {
+ Result.Data<SessionWithPlaybackState?>(
+ SessionWithPlaybackState(session, playback.isActive())
+ )
}
- .filterNotNull()
+ }
}
}
.stateIn(
@@ -78,14 +76,14 @@
)
val connectedDeviceViewModel: StateFlow<ConnectedDeviceViewModel?> =
- combine(sessionWithPlayback, interactor.currentConnectedDevice) {
+ combine(sessionWithPlaybackState, interactor.currentConnectedDevice) {
mediaDeviceSession,
currentConnectedDevice ->
if (mediaDeviceSession !is Result.Data) {
return@combine null
}
ConnectedDeviceViewModel(
- if (mediaDeviceSession.data?.playback?.isActive == true) {
+ if (mediaDeviceSession.data?.isPlaybackActive == true) {
context.getString(
R.string.media_output_label_title,
mediaDeviceSession.data.session.appLabel
@@ -103,19 +101,16 @@
)
val deviceIconViewModel: StateFlow<DeviceIconViewModel?> =
- combine(sessionWithPlayback, interactor.currentConnectedDevice) {
+ combine(sessionWithPlaybackState, interactor.currentConnectedDevice) {
mediaDeviceSession,
currentConnectedDevice ->
if (mediaDeviceSession !is Result.Data) {
return@combine null
}
- if (mediaDeviceSession.data?.playback?.isActive == true) {
- val icon =
- currentConnectedDevice?.icon?.let { Icon.Loaded(it, null) }
- ?: Icon.Resource(
- com.android.internal.R.drawable.ic_bt_headphones_a2dp,
- null
- )
+ val icon: Icon =
+ currentConnectedDevice?.icon?.let { Icon.Loaded(it, null) }
+ ?: Icon.Resource(R.drawable.ic_media_home_devices, null)
+ if (mediaDeviceSession.data?.isPlaybackActive == true) {
DeviceIconViewModel.IsPlaying(
icon = icon,
iconColor =
@@ -125,7 +120,7 @@
)
} else {
DeviceIconViewModel.IsNotPlaying(
- icon = Icon.Resource(R.drawable.ic_media_home_devices, null),
+ icon = icon,
iconColor =
Color.Attribute(
com.android.internal.R.attr.materialColorOnSurfaceVariant
@@ -143,7 +138,7 @@
fun onBarClick(expandable: Expandable) {
uiEventLogger.log(VolumePanelUiEvent.VOLUME_PANEL_MEDIA_OUTPUT_CLICKED)
- val result = sessionWithPlayback.value
+ val result = sessionWithPlaybackState.value
actionsInteractor.onBarClick((result as? Result.Data)?.data, expandable)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
index 303ae97..11d31c6 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextManagerTest.java
@@ -58,12 +58,15 @@
import com.android.keyguard.logging.CarrierTextManagerLogger;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.log.LogBufferHelperKt;
import com.android.systemui.res.R;
+import com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel.FakeDeviceBasedSatelliteViewModel;
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository;
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel;
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.kotlin.JavaAdapter;
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
@@ -78,6 +81,8 @@
import java.util.HashMap;
import java.util.List;
+import kotlinx.coroutines.test.TestScope;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class CarrierTextManagerTest extends SysuiTestCase {
@@ -99,6 +104,8 @@
TEST_CARRIER, TEST_CARRIER, NAME_SOURCE_CARRIER_ID, 0xFFFFFF, "",
DATA_ROAMING_ENABLE, null, null, null, null, false, null, "");
private FakeWifiRepository mWifiRepository = new FakeWifiRepository();
+ private final FakeDeviceBasedSatelliteViewModel mSatelliteViewModel =
+ new FakeDeviceBasedSatelliteViewModel();
@Mock
private WakefulnessLifecycle mWakefulnessLifecycle;
@Mock
@@ -124,6 +131,10 @@
new CarrierTextManagerLogger(
LogBufferHelperKt.logcatLogBuffer("CarrierTextManagerLog"));
+ private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this);
+ private final TestScope mTestScope = mKosmos.getTestScope();
+ private final JavaAdapter mJavaAdapter = new JavaAdapter(mTestScope.getBackgroundScope());
+
private Void checkMainThread(InvocationOnMock inv) {
assertThat(mMainExecutor.isExecuting()).isTrue();
assertThat(mBgExecutor.isExecuting()).isFalse();
@@ -156,9 +167,18 @@
when(mTelephonyManager.getActiveModemCount()).thenReturn(3);
mCarrierTextManager = new CarrierTextManager.Builder(
- mContext, mContext.getResources(), mWifiRepository,
- mTelephonyManager, mTelephonyListenerManager, mWakefulnessLifecycle, mMainExecutor,
- mBgExecutor, mKeyguardUpdateMonitor, mLogger)
+ mContext,
+ mContext.getResources(),
+ mWifiRepository,
+ mSatelliteViewModel,
+ mJavaAdapter,
+ mTelephonyManager,
+ mTelephonyListenerManager,
+ mWakefulnessLifecycle,
+ mMainExecutor,
+ mBgExecutor,
+ mKeyguardUpdateMonitor,
+ mLogger)
.setShowAirplaneMode(true)
.setShowMissingSim(true)
.build();
@@ -211,6 +231,8 @@
getContextSpyForStickyBroadcast(stickyIntent),
mContext.getResources(),
mWifiRepository,
+ mSatelliteViewModel,
+ mJavaAdapter,
mTelephonyManager,
mTelephonyListenerManager,
mWakefulnessLifecycle,
@@ -451,6 +473,107 @@
}
@Test
+ public void carrierText_satelliteTextNull_notUsed() {
+ reset(mCarrierTextCallback);
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
+ TelephonyManager.SIM_STATE_READY);
+ when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo()).thenReturn(list);
+ mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+ // WHEN the satellite text is null
+ mSatelliteViewModel.getCarrierText().setValue(null);
+ mTestScope.getTestScheduler().runCurrent();
+
+ ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextManager.CarrierTextCallbackInfo.class);
+ FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
+
+ // THEN the default subscription carrier text is used
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+ assertThat(captor.getValue().carrierText).isEqualTo(TEST_CARRIER);
+ }
+
+ @Test
+ public void carrierText_satelliteTextUpdates_autoTriggersCallback() {
+ reset(mCarrierTextCallback);
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
+ TelephonyManager.SIM_STATE_READY);
+ when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo()).thenReturn(list);
+ mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+ // WHEN the satellite text is set
+ mSatelliteViewModel.getCarrierText().setValue("Test satellite text");
+ mTestScope.getTestScheduler().runCurrent();
+
+ // THEN we should automatically re-trigger #updateCarrierText and get callback info
+ ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextManager.CarrierTextCallbackInfo.class);
+ FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+ // AND use the satellite text as the carrier text
+ assertThat(captor.getValue().carrierText).isEqualTo("Test satellite text");
+
+ // WHEN the satellite text is reset to null
+ reset(mCarrierTextCallback);
+ mSatelliteViewModel.getCarrierText().setValue(null);
+ mTestScope.getTestScheduler().runCurrent();
+
+ // THEN we should automatically re-trigger #updateCarrierText and get callback info
+ // that doesn't include the satellite info
+ FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+ assertThat(captor.getValue().carrierText).isEqualTo(TEST_CARRIER);
+ }
+
+ @Test
+ public void carrierText_updatedWhileNotListening_getsNewValueWhenListening() {
+ reset(mCarrierTextCallback);
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
+ TelephonyManager.SIM_STATE_READY);
+ when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo()).thenReturn(list);
+ mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+ mSatelliteViewModel.getCarrierText().setValue("Old satellite text");
+ mTestScope.getTestScheduler().runCurrent();
+
+ ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextManager.CarrierTextCallbackInfo.class);
+ FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+ assertThat(captor.getValue().carrierText).isEqualTo("Old satellite text");
+
+ // WHEN we stop listening
+ reset(mCarrierTextCallback);
+ mCarrierTextManager.setListening(null);
+
+ // AND the satellite text updates
+ mSatelliteViewModel.getCarrierText().setValue("New satellite text");
+
+ // THEN we don't get new callback info because we aren't listening
+ verify(mCarrierTextCallback, never()).updateCarrierInfo(any());
+
+ // WHEN we start listening again
+ reset(mCarrierTextCallback);
+ mCarrierTextManager.setListening(mCarrierTextCallback);
+
+ // THEN we should automatically re-trigger #updateCarrierText and get callback info
+ // that includes the new satellite text
+ mTestScope.getTestScheduler().runCurrent();
+ FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+ assertThat(captor.getValue().carrierText).isEqualTo("New satellite text");
+ }
+
+ @Test
public void testCreateInfo_noSubscriptions() {
reset(mCarrierTextCallback);
when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo()).thenReturn(
@@ -471,6 +594,28 @@
}
@Test
+ public void testCarrierText_oneValidSubscription() {
+ reset(mCarrierTextCallback);
+ List<SubscriptionInfo> list = new ArrayList<>();
+ list.add(TEST_SUBSCRIPTION);
+ when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
+ TelephonyManager.SIM_STATE_READY);
+ when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo()).thenReturn(list);
+
+ mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
+
+ ArgumentCaptor<CarrierTextManager.CarrierTextCallbackInfo> captor =
+ ArgumentCaptor.forClass(
+ CarrierTextManager.CarrierTextCallbackInfo.class);
+
+ mCarrierTextManager.updateCarrierText();
+ FakeExecutor.exhaustExecutors(mMainExecutor, mBgExecutor);
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+
+ assertThat(captor.getValue().carrierText).isEqualTo(TEST_CARRIER);
+ }
+
+ @Test
public void testCarrierText_twoValidSubscriptions() {
reset(mCarrierTextCallback);
List<SubscriptionInfo> list = new ArrayList<>();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 68b6d9d..d354fa2 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -2016,6 +2016,16 @@
}
@Test
+ public void unfoldFromPostureChange_sendActionToFaceAuthInteractor() {
+ // WHEN device posture changes to unfold
+ deviceInPostureStateOpened();
+ mTestableLooper.processAllMessages();
+
+ // THEN request face auth
+ verify(mFaceAuthInteractor).onDeviceUnfolded();
+ }
+
+ @Test
public void detectFingerprint_onTemporaryLockoutReset_authenticateFingerprint() {
ArgumentCaptor<FingerprintManager.LockoutResetCallback> fpLockoutResetCallbackCaptor =
ArgumentCaptor.forClass(FingerprintManager.LockoutResetCallback.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepositoryTest.kt
index d48b600..b3e845f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/BiometricStatusRepositoryTest.kt
@@ -36,7 +36,6 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.withArgCaptor
import com.google.common.truth.Truth.assertThat
@@ -65,8 +64,8 @@
@Before
fun setUp() {
- mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
- underTest = BiometricStatusRepositoryImpl(kosmos.testScope.backgroundScope, biometricManager)
+ underTest =
+ BiometricStatusRepositoryImpl(kosmos.testScope.backgroundScope, biometricManager)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractorImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractorImplTest.kt
index be5c7bc..4cff3e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractorImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/domain/interactor/BiometricStatusInteractorImplTest.kt
@@ -29,7 +29,6 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.shared.model.AcquiredFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -51,7 +50,6 @@
@Before
fun setup() {
- mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
underTest = kosmos.biometricStatusInteractor
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
index a603be4..01d9df8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/binder/SideFpsOverlayViewBinderTest.kt
@@ -78,7 +78,6 @@
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
import com.android.systemui.statusbar.phone.dozeServiceHost
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.testKosmos
@@ -175,8 +174,6 @@
@Before
fun setup() {
- mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
-
allowTestableLooperAsMainThread() // repeatWhenAttached requires the main thread
mContext = spy(mContext)
@@ -203,8 +200,11 @@
)
biometricStatusInteractor =
- BiometricStatusInteractorImpl(activityTaskManager, biometricStatusRepository,
- fingerprintPropertyRepository)
+ BiometricStatusInteractorImpl(
+ activityTaskManager,
+ biometricStatusRepository,
+ fingerprintPropertyRepository
+ )
displayStateInteractor =
DisplayStateInteractorImpl(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt
index 415da02..05ec64e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/SideFpsOverlayViewModelTest.kt
@@ -77,7 +77,6 @@
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneInteractor
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
import com.android.systemui.statusbar.phone.dozeServiceHost
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.testKosmos
@@ -176,8 +175,6 @@
@Before
fun setup() {
- mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
-
mContext = spy(mContext)
val resources = mContext.resources
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupHelperTest.kt
new file mode 100644
index 0000000..7094848
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupHelperTest.kt
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2024 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.communal.data.backup
+
+import android.app.backup.BackupDataInput
+import android.app.backup.BackupDataInputStream
+import android.app.backup.BackupDataOutput
+import android.os.UserHandle
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
+import androidx.room.Room
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.Flags
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.data.backup.CommunalBackupUtilsTest.Companion.represents
+import com.android.systemui.communal.data.backup.CommunalBackupUtilsTest.FakeWidgetMetadata
+import com.android.systemui.communal.data.db.CommunalDatabase
+import com.android.systemui.communal.data.db.CommunalWidgetDao
+import com.android.systemui.communal.proto.toCommunalHubState
+import com.android.systemui.lifecycle.InstantTaskExecutorRule
+import com.google.common.truth.Truth.assertThat
+import java.io.File
+import java.io.FileInputStream
+import java.io.FileOutputStream
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CommunalBackupHelperTest : SysuiTestCase() {
+ @JvmField @Rule val instantTaskExecutor = InstantTaskExecutorRule()
+
+ private lateinit var database: CommunalDatabase
+ private lateinit var dao: CommunalWidgetDao
+ private lateinit var backupUtils: CommunalBackupUtils
+
+ // Temporary file used for storing backed-up data.
+ private lateinit var backupDataFile: File
+
+ private lateinit var underTest: CommunalBackupHelper
+
+ @Before
+ fun setup() {
+ database =
+ Room.inMemoryDatabaseBuilder(context, CommunalDatabase::class.java)
+ .allowMainThreadQueries()
+ .build()
+ CommunalDatabase.setInstance(database)
+
+ dao = database.communalWidgetDao()
+ backupUtils = CommunalBackupUtils(context)
+
+ backupDataFile = File(context.cacheDir, "backup_data_file")
+
+ underTest = CommunalBackupHelper(UserHandle.SYSTEM, backupUtils)
+ }
+
+ @After
+ fun teardown() {
+ backupDataFile.delete()
+ database.close()
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_COMMUNAL_HUB)
+ fun backupAndRestoreCommunalHub() {
+ val expectedWidgets = setUpDatabase()
+
+ underTest.performBackup(oldState = null, data = getBackupDataOutput(), newState = null)
+ underTest.restoreEntity(getBackupDataInputStream())
+
+ // Verify restored state matches backed-up state
+ val restoredState = backupUtils.readBytesFromDisk().toCommunalHubState()
+ val restoredWidgets = restoredState.widgets.toList()
+ assertThat(restoredWidgets)
+ .comparingElementsUsing(represents)
+ .containsExactlyElementsIn(expectedWidgets)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_COMMUNAL_HUB)
+ fun backup_skippedWhenCommunalDisabled() {
+ setUpDatabase()
+
+ underTest.performBackup(oldState = null, data = getBackupDataOutput(), newState = null)
+
+ // Verify nothing written to the backup
+ assertThat(backupDataFile.length()).isEqualTo(0)
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_COMMUNAL_HUB)
+ fun backup_skippedForNonSystemUser() {
+ setUpDatabase()
+
+ val helper = CommunalBackupHelper(UserHandle.CURRENT, backupUtils)
+ helper.performBackup(oldState = null, data = getBackupDataOutput(), newState = null)
+
+ // Verify nothing written to the backup
+ assertThat(backupDataFile.length()).isEqualTo(0)
+ }
+
+ private fun setUpDatabase(): List<FakeWidgetMetadata> {
+ return listOf(
+ FakeWidgetMetadata(11, "com.android.fakePackage1/fakeWidget1", 3),
+ FakeWidgetMetadata(12, "com.android.fakePackage2/fakeWidget2", 2),
+ FakeWidgetMetadata(13, "com.android.fakePackage3/fakeWidget3", 1),
+ )
+ .onEach { dao.addWidget(it.widgetId, it.componentName, it.rank) }
+ }
+
+ private fun getBackupDataInputStream(): BackupDataInputStream {
+ val input = BackupDataInput(FileInputStream(backupDataFile).fd).apply { readNextHeader() }
+
+ // Construct BackupDataInputStream using reflection because its constructor is package
+ // private
+ val inputStream = BackupDataInputStream::class.constructors.first().call(input)
+
+ // Set key
+ with(inputStream.javaClass.getDeclaredField("key")) {
+ isAccessible = true
+ set(inputStream, input.key)
+ }
+
+ // Set dataSize
+ with(inputStream.javaClass.getDeclaredField("dataSize")) {
+ isAccessible = true
+ set(inputStream, input.dataSize)
+ }
+
+ return inputStream
+ }
+
+ private fun getBackupDataOutput(): BackupDataOutput {
+ return BackupDataOutput(FileOutputStream(backupDataFile).fd)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupUtilsTest.kt
new file mode 100644
index 0000000..bed05ee
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/data/backup/CommunalBackupUtilsTest.kt
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2024 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.communal.data.backup
+
+import androidx.room.Room
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.data.db.CommunalDatabase
+import com.android.systemui.communal.data.db.CommunalWidgetDao
+import com.android.systemui.communal.nano.CommunalHubState
+import com.android.systemui.lifecycle.InstantTaskExecutorRule
+import com.google.common.truth.Correspondence
+import com.google.common.truth.Truth.assertThat
+import java.io.FileNotFoundException
+import java.nio.charset.Charset
+import org.junit.After
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CommunalBackupUtilsTest : SysuiTestCase() {
+ @JvmField @Rule val instantTaskExecutor = InstantTaskExecutorRule()
+
+ private lateinit var database: CommunalDatabase
+ private lateinit var dao: CommunalWidgetDao
+ private lateinit var underTest: CommunalBackupUtils
+
+ @Before
+ fun setup() {
+ database =
+ Room.inMemoryDatabaseBuilder(context, CommunalDatabase::class.java)
+ .allowMainThreadQueries()
+ .build()
+ CommunalDatabase.setInstance(database)
+
+ dao = database.communalWidgetDao()
+ underTest = CommunalBackupUtils(context)
+ }
+
+ @After
+ fun teardown() {
+ database.close()
+ underTest.clear()
+ }
+
+ @Test
+ fun getCommunalHubState_returnsExpectedWidgets() {
+ // Set up database
+ val expectedWidgets =
+ listOf(
+ FakeWidgetMetadata(11, "com.android.fakePackage1/fakeWidget1", 3),
+ FakeWidgetMetadata(12, "com.android.fakePackage2/fakeWidget2", 2),
+ FakeWidgetMetadata(13, "com.android.fakePackage3/fakeWidget3", 1),
+ )
+ expectedWidgets.forEach { dao.addWidget(it.widgetId, it.componentName, it.rank) }
+
+ // Get communal hub state
+ val state = underTest.getCommunalHubState()
+ val actualWidgets = state.widgets.toList()
+
+ // Verify the state contains widgets as expected
+ assertThat(actualWidgets)
+ .comparingElementsUsing(represents)
+ .containsExactlyElementsIn(expectedWidgets)
+ }
+
+ @Test
+ fun write_existingContentIsOverwritten() {
+ // Write old data
+ val dataToWrite = "I am old data. Erase me."
+ underTest.writeBytesToDisk(dataToWrite.toByteArray(Charset.defaultCharset()))
+
+ // Verify old data written
+ var dataRead = underTest.readBytesFromDisk().toString(Charset.defaultCharset())
+ assertThat(dataRead).isEqualTo(dataToWrite)
+
+ // Write new data
+ val newDataToWrite = "I am new data."
+ underTest.writeBytesToDisk(newDataToWrite.toByteArray(Charset.defaultCharset()))
+
+ // Verify new data overwrites old
+ dataRead = underTest.readBytesFromDisk().toString(Charset.defaultCharset())
+ assertThat(dataRead).isEqualTo(newDataToWrite)
+ }
+
+ @Ignore("Ignored until we figure out why it is flaky b/336561027")
+ @Test(expected = FileNotFoundException::class)
+ fun read_fileNotFoundException() {
+ underTest.readBytesFromDisk()
+ }
+
+ @Test(expected = FileNotFoundException::class)
+ fun clear_returnsTrueWhenFileDeleted() {
+ // Write bytes to disk
+ underTest.writeBytesToDisk(byteArrayOf(1, 2, 3))
+
+ assertThat(underTest.clear()).isTrue()
+
+ // Verify a read after that throws a FileNotFoundException
+ underTest.readBytesFromDisk()
+ }
+
+ @Test
+ fun clear_returnsFalseWhenFileDoesNotExist() {
+ assertThat(underTest.clear()).isFalse()
+ }
+
+ @Test
+ fun fileExists() {
+ assertThat(underTest.fileExists()).isFalse()
+
+ underTest.writeBytesToDisk(byteArrayOf(1, 2, 3))
+ assertThat(underTest.fileExists()).isTrue()
+
+ underTest.clear()
+ assertThat(underTest.fileExists()).isFalse()
+ }
+
+ data class FakeWidgetMetadata(val widgetId: Int, val componentName: String, val rank: Int)
+
+ companion object {
+ /**
+ * A comparator for whether a [CommunalHubState.CommunalWidgetItem] represents a
+ * [FakeWidgetMetadata]
+ */
+ val represents: Correspondence<CommunalHubState.CommunalWidgetItem, FakeWidgetMetadata> =
+ Correspondence.from(
+ { actual, expected ->
+ actual?.widgetId == expected?.widgetId &&
+ actual?.componentName == expected?.componentName &&
+ actual?.rank == expected?.rank
+ },
+ "represents",
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalWidgetDaoTest.kt b/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalWidgetDaoTest.kt
index 20dd913..f77c7a6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalWidgetDaoTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/data/db/CommunalWidgetDaoTest.kt
@@ -21,6 +21,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.nano.CommunalHubState
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.lifecycle.InstantTaskExecutorRule
import com.google.common.truth.Truth.assertThat
@@ -224,6 +225,42 @@
.inOrder()
}
+ @Test
+ fun restoreCommunalHubState() =
+ testScope.runTest {
+ // Set up db
+ listOf(widgetInfo1, widgetInfo2, widgetInfo3).forEach { addWidget(it) }
+
+ // Restore db to fake state
+ communalWidgetDao.restoreCommunalHubState(fakeState)
+
+ // Verify db matches new state
+ val expected = mutableMapOf<CommunalItemRank, CommunalWidgetItem>()
+ fakeState.widgets.forEachIndexed { index, fakeWidget ->
+ // Auto-generated uid continues after the initial 3 widgets and starts at 4
+ val uid = index + 4L
+ val rank = CommunalItemRank(uid = uid, rank = fakeWidget.rank)
+ val widget =
+ CommunalWidgetItem(
+ uid = uid,
+ widgetId = fakeWidget.widgetId,
+ componentName = fakeWidget.componentName,
+ itemId = rank.uid,
+ )
+ expected[rank] = widget
+ }
+ val widgets by collectLastValue(communalWidgetDao.getWidgets())
+ assertThat(widgets).containsExactlyEntriesIn(expected)
+ }
+
+ private fun addWidget(metadata: FakeWidgetMetadata, priority: Int? = null) {
+ communalWidgetDao.addWidget(
+ widgetId = metadata.widgetId,
+ provider = metadata.provider,
+ priority = priority ?: metadata.priority,
+ )
+ }
+
data class FakeWidgetMetadata(
val widgetId: Int,
val provider: ComponentName,
@@ -273,5 +310,22 @@
componentName = widgetInfo3.provider.flattenToString(),
itemId = communalItemRankEntry3.uid,
)
+ val fakeState =
+ CommunalHubState().apply {
+ widgets =
+ listOf(
+ CommunalHubState.CommunalWidgetItem().apply {
+ widgetId = 1
+ componentName = "pk_name/fake_widget_1"
+ rank = 1
+ },
+ CommunalHubState.CommunalWidgetItem().apply {
+ widgetId = 2
+ componentName = "pk_name/fake_widget_2"
+ rank = 2
+ },
+ )
+ .toTypedArray()
+ }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SeekableSliderEventProducerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SeekableSliderEventProducerTest.kt
deleted file mode 100644
index c22d35c..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SeekableSliderEventProducerTest.kt
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2023 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.haptics.slider
-
-import android.widget.SeekBar
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import junit.framework.Assert.assertEquals
-import kotlinx.coroutines.test.runTest
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class SeekableSliderEventProducerTest : SysuiTestCase() {
-
- private val seekBar = SeekBar(mContext)
- private val eventProducer = SeekableSliderEventProducer()
- private val eventFlow = eventProducer.produceEvents()
-
- @Test
- fun onStartTrackingTouch_noProgress_trackingTouchEventProduced() = runTest {
- val latest by collectLastValue(eventFlow)
-
- eventProducer.onStartTrackingTouch(seekBar)
-
- assertEquals(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, 0F), latest)
- }
-
- @Test
- fun onStopTrackingTouch_noProgress_StoppedTrackingTouchEventProduced() = runTest {
- val latest by collectLastValue(eventFlow)
-
- eventProducer.onStopTrackingTouch(seekBar)
-
- assertEquals(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0F), latest)
- }
-
- @Test
- fun onProgressChangeByUser_changeByUserEventProduced_withNormalizedProgress() = runTest {
- val progress = 50
- val latest by collectLastValue(eventFlow)
-
- eventProducer.onProgressChanged(seekBar, progress, true)
-
- assertEquals(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, 0.5F), latest)
- }
-
- @Test
- fun onProgressChangeByUser_zeroWidthSlider_changeByUserEventProduced_withMaxProgress() =
- runTest {
- // No-width slider where the min and max values are the same
- seekBar.min = 100
- seekBar.max = 100
- val progress = 50
- val latest by collectLastValue(eventFlow)
-
- eventProducer.onProgressChanged(seekBar, progress, true)
-
- assertEquals(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, 1.0F), latest)
- }
-
- @Test
- fun onProgressChangeByProgram_changeByProgramEventProduced_withNormalizedProgress() = runTest {
- val progress = 50
- val latest by collectLastValue(eventFlow)
-
- eventProducer.onProgressChanged(seekBar, progress, false)
-
- assertEquals(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, 0.5F), latest)
- }
-
- @Test
- fun onProgressChangeByProgram_zeroWidthSlider_changeByProgramEventProduced_withMaxProgress() =
- runTest {
- // No-width slider where the min and max values are the same
- seekBar.min = 100
- seekBar.max = 100
- val progress = 50
- val latest by collectLastValue(eventFlow)
-
- eventProducer.onProgressChanged(seekBar, progress, false)
-
- assertEquals(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, 1.0F), latest)
- }
-
- @Test
- fun onStartTrackingTouch_afterProgress_trackingTouchEventProduced_withNormalizedProgress() =
- runTest {
- val progress = 50
- val latest by collectLastValue(eventFlow)
-
- eventProducer.onProgressChanged(seekBar, progress, true)
- eventProducer.onStartTrackingTouch(seekBar)
-
- assertEquals(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, 0.5F), latest)
- }
-
- @Test
- fun onStopTrackingTouch_afterProgress_stopTrackingTouchEventProduced_withNormalizedProgress() =
- runTest {
- val progress = 50
- val latest by collectLastValue(eventFlow)
-
- eventProducer.onProgressChanged(seekBar, progress, true)
- eventProducer.onStopTrackingTouch(seekBar)
-
- assertEquals(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5F), latest)
- }
-
- @Test
- fun onArrowUp_afterStartTrackingTouch_ArrowUpProduced() = runTest {
- val latest by collectLastValue(eventFlow)
-
- eventProducer.onStartTrackingTouch(seekBar)
- eventProducer.onArrowUp()
-
- assertEquals(SliderEvent(SliderEventType.ARROW_UP, 0f), latest)
- }
-
- @Test
- fun onArrowUp_afterChangeByProgram_ArrowUpProduced_withProgress() = runTest {
- val progress = 50
- val latest by collectLastValue(eventFlow)
-
- eventProducer.onProgressChanged(seekBar, progress, false)
- eventProducer.onArrowUp()
-
- assertEquals(SliderEvent(SliderEventType.ARROW_UP, 0.5f), latest)
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SeekableSliderTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderStateTrackerTest.kt
similarity index 79%
rename from packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SeekableSliderTrackerTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderStateTrackerTest.kt
index 796d6d9..a09d345 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SeekableSliderTrackerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/haptics/slider/SliderStateTrackerTest.kt
@@ -38,11 +38,11 @@
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
-class SeekableSliderTrackerTest : SysuiTestCase() {
+class SliderStateTrackerTest : SysuiTestCase() {
@Mock private lateinit var sliderStateListener: SliderStateListener
private val sliderEventProducer = FakeSliderEventProducer()
- private lateinit var mSeekableSliderTracker: SeekableSliderTracker
+ private lateinit var mSliderStateTracker: SliderStateTracker
@Before
fun setup() {
@@ -55,7 +55,7 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
// THEN the tracker job is active
- assertThat(mSeekableSliderTracker.isTracking).isTrue()
+ assertThat(mSliderStateTracker.isTracking).isTrue()
}
@Test
@@ -65,14 +65,14 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
// GIVEN a state in the state machine
- mSeekableSliderTracker.setState(it)
+ mSliderStateTracker.setState(it)
// WHEN the tracker stops tracking the state and listening to events
- mSeekableSliderTracker.stopTracking()
+ mSliderStateTracker.stopTracking()
// THEN The state is idle and the tracker is not active
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
- assertThat(mSeekableSliderTracker.isTracking).isFalse()
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+ assertThat(mSliderStateTracker.isTracking).isFalse()
}
}
@@ -83,7 +83,7 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
// THEN The state is idle and the listener is not called to play haptics
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
verifyZeroInteractions(sliderStateListener)
}
@@ -96,9 +96,9 @@
sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
// THEN the tracker moves to the wait state and the timer job begins
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.WAIT)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.WAIT)
verifyZeroInteractions(sliderStateListener)
- assertThat(mSeekableSliderTracker.isWaiting).isTrue()
+ assertThat(mSliderStateTracker.isWaiting).isTrue()
}
// Tests on the WAIT state
@@ -117,9 +117,9 @@
advanceTimeBy(config.waitTimeMillis + 10L)
// THEN the tracker moves to the DRAG_HANDLE_ACQUIRED_BY_TOUCH state
- assertThat(mSeekableSliderTracker.currentState)
+ assertThat(mSliderStateTracker.currentState)
.isEqualTo(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
- assertThat(mSeekableSliderTracker.isWaiting).isFalse()
+ assertThat(mSliderStateTracker.isWaiting).isFalse()
verify(sliderStateListener).onHandleAcquiredByTouch()
verifyNoMoreInteractions(sliderStateListener)
}
@@ -142,9 +142,9 @@
// THEN the tracker moves to the DRAG_HANDLE_ACQUIRED_BY_TOUCH state without the timer job
// being complete
- assertThat(mSeekableSliderTracker.currentState)
+ assertThat(mSliderStateTracker.currentState)
.isEqualTo(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
- assertThat(mSeekableSliderTracker.isWaiting).isFalse()
+ assertThat(mSliderStateTracker.isWaiting).isFalse()
verify(sliderStateListener).onHandleAcquiredByTouch()
verifyNoMoreInteractions(sliderStateListener)
}
@@ -166,9 +166,9 @@
)
// THEN the tracker moves to the jump-track location selected state
- assertThat(mSeekableSliderTracker.currentState)
+ assertThat(mSliderStateTracker.currentState)
.isEqualTo(SliderState.JUMP_TRACK_LOCATION_SELECTED)
- assertThat(mSeekableSliderTracker.isWaiting).isFalse()
+ assertThat(mSliderStateTracker.isWaiting).isFalse()
verify(sliderStateListener).onProgressJump(anyFloat())
verifyNoMoreInteractions(sliderStateListener)
}
@@ -190,8 +190,8 @@
)
// THEN the tracker moves to the jump-track location selected state
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.JUMP_BOOKEND_SELECTED)
- assertThat(mSeekableSliderTracker.isWaiting).isFalse()
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.JUMP_BOOKEND_SELECTED)
+ assertThat(mSliderStateTracker.isWaiting).isFalse()
verifyNoMoreInteractions(sliderStateListener)
}
@@ -212,8 +212,8 @@
)
// THEN the tracker moves to the JUMP_TRACK_LOCATION_SELECTED state
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.JUMP_BOOKEND_SELECTED)
- assertThat(mSeekableSliderTracker.isWaiting).isFalse()
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.JUMP_BOOKEND_SELECTED)
+ assertThat(mSliderStateTracker.isWaiting).isFalse()
verifyNoMoreInteractions(sliderStateListener)
}
@@ -225,15 +225,15 @@
// GIVEN a start of tracking touch event that moves the tracker to WAIT at the middle of the
// slider
sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, 0.5f))
- assertThat(mSeekableSliderTracker.isWaiting).isTrue()
+ assertThat(mSliderStateTracker.isWaiting).isTrue()
// GIVEN that the tracker stops tracking the state and listening to events
- mSeekableSliderTracker.stopTracking()
+ mSliderStateTracker.stopTracking()
// THEN the tracker moves to the IDLE state without the timer job being complete
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
- assertThat(mSeekableSliderTracker.isWaiting).isFalse()
- assertThat(mSeekableSliderTracker.isTracking).isFalse()
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
+ assertThat(mSliderStateTracker.isWaiting).isFalse()
+ assertThat(mSliderStateTracker.isTracking).isFalse()
verifyNoMoreInteractions(sliderStateListener)
}
@@ -244,13 +244,13 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
// GIVEN a JUMP_TRACK_LOCATION_SELECTED state
- mSeekableSliderTracker.setState(SliderState.JUMP_TRACK_LOCATION_SELECTED)
+ mSliderStateTracker.setState(SliderState.JUMP_TRACK_LOCATION_SELECTED)
// GIVEN a progress event due to dragging the handle
sliderEventProducer.sendEvent(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, 0.5f))
// THEN the tracker moves to the DRAG_HANDLE_DRAGGING state
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
verify(sliderStateListener).onProgress(anyFloat())
verifyNoMoreInteractions(sliderStateListener)
}
@@ -260,14 +260,14 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
// GIVEN a JUMP_TRACK_LOCATION_SELECTED state
- mSeekableSliderTracker.setState(SliderState.JUMP_TRACK_LOCATION_SELECTED)
+ mSliderStateTracker.setState(SliderState.JUMP_TRACK_LOCATION_SELECTED)
// GIVEN that the slider stopped tracking touch
sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5f))
// THEN the tracker executes on onHandleReleasedFromTouch before moving to the IDLE state
verify(sliderStateListener).onHandleReleasedFromTouch()
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
verifyNoMoreInteractions(sliderStateListener)
}
@@ -276,13 +276,13 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
// GIVEN a JUMP_BOOKEND_SELECTED state
- mSeekableSliderTracker.setState(SliderState.JUMP_BOOKEND_SELECTED)
+ mSliderStateTracker.setState(SliderState.JUMP_BOOKEND_SELECTED)
// GIVEN that the slider stopped tracking touch
sliderEventProducer.sendEvent(SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_USER, 0.5f))
// THEN the tracker moves to the DRAG_HANDLE_DRAGGING state
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
verify(sliderStateListener).onProgress(anyFloat())
verifyNoMoreInteractions(sliderStateListener)
}
@@ -292,14 +292,14 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
// GIVEN a JUMP_BOOKEND_SELECTED state
- mSeekableSliderTracker.setState(SliderState.JUMP_BOOKEND_SELECTED)
+ mSliderStateTracker.setState(SliderState.JUMP_BOOKEND_SELECTED)
// GIVEN that the slider stopped tracking touch
sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5f))
// THEN the tracker executes on onHandleReleasedFromTouch before moving to the IDLE state
verify(sliderStateListener).onHandleReleasedFromTouch()
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
verifyNoMoreInteractions(sliderStateListener)
}
@@ -310,7 +310,7 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
// GIVEN a DRAG_HANDLE_ACQUIRED_BY_TOUCH state
- mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
+ mSliderStateTracker.setState(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
// GIVEN a progress change by the user
val progress = 0.5f
@@ -320,7 +320,7 @@
// THEN the tracker moves to the DRAG_HANDLE_DRAGGING state
verify(sliderStateListener).onProgress(progress)
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
verifyNoMoreInteractions(sliderStateListener)
}
@@ -329,14 +329,14 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
// GIVEN a DRAG_HANDLE_ACQUIRED_BY_TOUCH state
- mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
+ mSliderStateTracker.setState(SliderState.DRAG_HANDLE_ACQUIRED_BY_TOUCH)
// GIVEN that the handle stops tracking touch
sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5f))
// THEN the tracker executes on onHandleReleasedFromTouch before moving to the IDLE state
verify(sliderStateListener).onHandleReleasedFromTouch()
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
verifyNoMoreInteractions(sliderStateListener)
}
@@ -348,7 +348,7 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
// GIVEN a DRAG_HANDLE_DRAGGING state
- mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
+ mSliderStateTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
// GIVEN a progress change by the user outside of bookend bounds
val progress = 0.5f
@@ -357,8 +357,7 @@
)
// THEN the tracker does not change state and executes the onProgress call
- assertThat(mSeekableSliderTracker.currentState)
- .isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
verify(sliderStateListener).onProgress(progress)
verifyNoMoreInteractions(sliderStateListener)
}
@@ -370,7 +369,7 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
// GIVEN a DRAG_HANDLE_DRAGGING state
- mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
+ mSliderStateTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
// GIVEN a progress change by the user reaching the lower bookend
val progress = config.lowerBookendThreshold - 0.01f
@@ -380,7 +379,7 @@
// THEN the tracker moves to the DRAG_HANDLE_REACHED_BOOKEND state and executes the
// corresponding callback
- assertThat(mSeekableSliderTracker.currentState)
+ assertThat(mSliderStateTracker.currentState)
.isEqualTo(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
verify(sliderStateListener).onLowerBookend()
verifyNoMoreInteractions(sliderStateListener)
@@ -393,7 +392,7 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
// GIVEN a DRAG_HANDLE_DRAGGING state
- mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
+ mSliderStateTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
// GIVEN a progress change by the user reaching the upper bookend
val progress = config.upperBookendThreshold + 0.01f
@@ -403,7 +402,7 @@
// THEN the tracker moves to the DRAG_HANDLE_REACHED_BOOKEND state and executes the
// corresponding callback
- assertThat(mSeekableSliderTracker.currentState)
+ assertThat(mSliderStateTracker.currentState)
.isEqualTo(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
verify(sliderStateListener).onUpperBookend()
verifyNoMoreInteractions(sliderStateListener)
@@ -414,14 +413,14 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
// GIVEN a DRAG_HANDLE_DRAGGING state
- mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
+ mSliderStateTracker.setState(SliderState.DRAG_HANDLE_DRAGGING)
// GIVEN that the slider stops tracking touch
sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5f))
// THEN the tracker executes on onHandleReleasedFromTouch before moving to the IDLE state
verify(sliderStateListener).onHandleReleasedFromTouch()
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
verifyNoMoreInteractions(sliderStateListener)
}
@@ -434,7 +433,7 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
// GIVEN a DRAG_HANDLE_REACHED_BOOKEND state
- mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
+ mSliderStateTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
// GIVEN a progress event that falls outside of the lower bookend range
val progress = config.lowerBookendThreshold + 0.01f
@@ -444,8 +443,7 @@
// THEN the tracker moves to the DRAG_HANDLE_DRAGGING state and executes accordingly
verify(sliderStateListener).onProgress(progress)
- assertThat(mSeekableSliderTracker.currentState)
- .isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
verifyNoMoreInteractions(sliderStateListener)
}
@@ -455,7 +453,7 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
// GIVEN a DRAG_HANDLE_REACHED_BOOKEND state
- mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
+ mSliderStateTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
// GIVEN a progress event that falls inside of the lower bookend range
val progress = config.lowerBookendThreshold - 0.01f
@@ -465,7 +463,7 @@
// THEN the tracker stays in the current state and executes accordingly
verify(sliderStateListener).onLowerBookend()
- assertThat(mSeekableSliderTracker.currentState)
+ assertThat(mSliderStateTracker.currentState)
.isEqualTo(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
verifyNoMoreInteractions(sliderStateListener)
}
@@ -477,7 +475,7 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
// GIVEN a DRAG_HANDLE_REACHED_BOOKEND state
- mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
+ mSliderStateTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
// GIVEN a progress event that falls outside of the upper bookend range
val progress = config.upperBookendThreshold - 0.01f
@@ -487,8 +485,7 @@
// THEN the tracker moves to the DRAG_HANDLE_DRAGGING state and executes accordingly
verify(sliderStateListener).onProgress(progress)
- assertThat(mSeekableSliderTracker.currentState)
- .isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.DRAG_HANDLE_DRAGGING)
verifyNoMoreInteractions(sliderStateListener)
}
@@ -498,7 +495,7 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
// GIVEN a DRAG_HANDLE_REACHED_BOOKEND state
- mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
+ mSliderStateTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
// GIVEN a progress event that falls inside of the upper bookend range
val progress = config.upperBookendThreshold + 0.01f
@@ -508,7 +505,7 @@
// THEN the tracker stays in the current state and executes accordingly
verify(sliderStateListener).onUpperBookend()
- assertThat(mSeekableSliderTracker.currentState)
+ assertThat(mSliderStateTracker.currentState)
.isEqualTo(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
verifyNoMoreInteractions(sliderStateListener)
}
@@ -518,37 +515,36 @@
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
// GIVEN a DRAG_HANDLE_REACHED_BOOKEND state
- mSeekableSliderTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
+ mSliderStateTracker.setState(SliderState.DRAG_HANDLE_REACHED_BOOKEND)
// GIVEN that the handle stops tracking touch
sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STOPPED_TRACKING_TOUCH, 0.5f))
// THEN the tracker executes on onHandleReleasedFromTouch before moving to the IDLE state
verify(sliderStateListener).onHandleReleasedFromTouch()
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
verifyNoMoreInteractions(sliderStateListener)
}
@Test
- fun onProgressChangeByProgram_atTheMiddle_onIdle_movesToArrowHandleMovedOnce() = runTest {
+ fun onStartedTrackingProgram_atTheMiddle_onIdle_movesToArrowHandleMovedOnce() = runTest {
// GIVEN an initialized tracker in the IDLE state
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
// GIVEN a progress due to an external source that lands at the middle of the slider
val progress = 0.5f
sliderEventProducer.sendEvent(
- SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress)
+ SliderEvent(SliderEventType.STARTED_TRACKING_PROGRAM, progress)
)
// THEN the state moves to ARROW_HANDLE_MOVED_ONCE and the listener is called to play
// haptics
- assertThat(mSeekableSliderTracker.currentState)
- .isEqualTo(SliderState.ARROW_HANDLE_MOVED_ONCE)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.ARROW_HANDLE_MOVED_ONCE)
verify(sliderStateListener).onSelectAndArrow(progress)
}
@Test
- fun onProgressChangeByProgram_atUpperBookend_onIdle_movesToIdle() = runTest {
+ fun onStartedTrackingProgram_atUpperBookend_onIdle_movesToIdle() = runTest {
// GIVEN an initialized tracker in the IDLE state
val config = SeekableSliderTrackerConfig()
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
@@ -556,16 +552,16 @@
// GIVEN a progress due to an external source that lands at the upper bookend
val progress = config.upperBookendThreshold + 0.01f
sliderEventProducer.sendEvent(
- SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress)
+ SliderEvent(SliderEventType.STARTED_TRACKING_PROGRAM, progress)
)
// THEN the tracker executes upper bookend haptics before moving back to IDLE
verify(sliderStateListener).onUpperBookend()
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
}
@Test
- fun onProgressChangeByProgram_atLowerBookend_onIdle_movesToIdle() = runTest {
+ fun onStartedTrackingProgram_atLowerBookend_onIdle_movesToIdle() = runTest {
// GIVEN an initialized tracker in the IDLE state
val config = SeekableSliderTrackerConfig()
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
@@ -573,26 +569,28 @@
// WHEN a progress is recorded due to an external source that lands at the lower bookend
val progress = config.lowerBookendThreshold - 0.01f
sliderEventProducer.sendEvent(
- SliderEvent(SliderEventType.PROGRESS_CHANGE_BY_PROGRAM, progress)
+ SliderEvent(SliderEventType.STARTED_TRACKING_PROGRAM, progress)
)
// THEN the tracker executes lower bookend haptics before moving to IDLE
verify(sliderStateListener).onLowerBookend()
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
}
@Test
fun onArrowUp_onArrowMovedOnce_movesToIdle() = runTest {
// GIVEN an initialized tracker in the ARROW_HANDLE_MOVED_ONCE state
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
- mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVED_ONCE)
+ mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVED_ONCE)
// WHEN the external stimulus is released
val progress = 0.5f
- sliderEventProducer.sendEvent(SliderEvent(SliderEventType.ARROW_UP, progress))
+ sliderEventProducer.sendEvent(
+ SliderEvent(SliderEventType.STOPPED_TRACKING_PROGRAM, progress)
+ )
// THEN the tracker moves back to IDLE and there are no haptics
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
verifyZeroInteractions(sliderStateListener)
}
@@ -600,7 +598,7 @@
fun onStartTrackingTouch_onArrowMovedOnce_movesToWait() = runTest {
// GIVEN an initialized tracker in the ARROW_HANDLE_MOVED_ONCE state
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
- mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVED_ONCE)
+ mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVED_ONCE)
// WHEN the slider starts tracking touch
val progress = 0.5f
@@ -608,8 +606,8 @@
// THEN the tracker moves back to WAIT and starts the waiting job. Also, there are no
// haptics
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.WAIT)
- assertThat(mSeekableSliderTracker.isWaiting).isTrue()
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.WAIT)
+ assertThat(mSliderStateTracker.isWaiting).isTrue()
verifyZeroInteractions(sliderStateListener)
}
@@ -617,7 +615,7 @@
fun onProgressChangeByProgram_onArrowMovedOnce_movesToArrowMovesContinuously() = runTest {
// GIVEN an initialized tracker in the ARROW_HANDLE_MOVED_ONCE state
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
- mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVED_ONCE)
+ mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVED_ONCE)
// WHEN the slider gets an external progress change
val progress = 0.5f
@@ -627,7 +625,7 @@
// THEN the tracker moves to ARROW_HANDLE_MOVES_CONTINUOUSLY and calls the appropriate
// haptics
- assertThat(mSeekableSliderTracker.currentState)
+ assertThat(mSliderStateTracker.currentState)
.isEqualTo(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
verify(sliderStateListener).onProgress(progress)
}
@@ -636,14 +634,16 @@
fun onArrowUp_onArrowMovesContinuously_movesToIdle() = runTest {
// GIVEN an initialized tracker in the ARROW_HANDLE_MOVES_CONTINUOUSLY state
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
- mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
+ mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
// WHEN the external stimulus is released
val progress = 0.5f
- sliderEventProducer.sendEvent(SliderEvent(SliderEventType.ARROW_UP, progress))
+ sliderEventProducer.sendEvent(
+ SliderEvent(SliderEventType.STOPPED_TRACKING_PROGRAM, progress)
+ )
// THEN the tracker moves to IDLE and no haptics are played
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
verifyZeroInteractions(sliderStateListener)
}
@@ -651,15 +651,15 @@
fun onStartTrackingTouch_onArrowMovesContinuously_movesToWait() = runTest {
// GIVEN an initialized tracker in the ARROW_HANDLE_MOVES_CONTINUOUSLY state
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
- mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
+ mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
// WHEN the slider starts tracking touch
val progress = 0.5f
sliderEventProducer.sendEvent(SliderEvent(SliderEventType.STARTED_TRACKING_TOUCH, progress))
// THEN the tracker moves to WAIT and the wait job starts.
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.WAIT)
- assertThat(mSeekableSliderTracker.isWaiting).isTrue()
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.WAIT)
+ assertThat(mSliderStateTracker.isWaiting).isTrue()
verifyZeroInteractions(sliderStateListener)
}
@@ -667,7 +667,7 @@
fun onProgressChangeByProgram_onArrowMovesContinuously_preservesState() = runTest {
// GIVEN an initialized tracker in the ARROW_HANDLE_MOVES_CONTINUOUSLY state
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)))
- mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
+ mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
// WHEN the slider changes progress programmatically at the middle
val progress = 0.5f
@@ -676,7 +676,7 @@
)
// THEN the tracker stays in the same state and haptics are delivered appropriately
- assertThat(mSeekableSliderTracker.currentState)
+ assertThat(mSliderStateTracker.currentState)
.isEqualTo(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
verify(sliderStateListener).onProgress(progress)
}
@@ -686,7 +686,7 @@
// GIVEN an initialized tracker in the ARROW_HANDLE_MOVES_CONTINUOUSLY state
val config = SeekableSliderTrackerConfig()
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
- mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
+ mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
// WHEN the slider reaches the lower bookend programmatically
val progress = config.lowerBookendThreshold - 0.01f
@@ -696,7 +696,7 @@
// THEN the tracker executes lower bookend haptics before moving to IDLE
verify(sliderStateListener).onLowerBookend()
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
}
@Test
@@ -704,7 +704,7 @@
// GIVEN an initialized tracker in the ARROW_HANDLE_MOVES_CONTINUOUSLY state
val config = SeekableSliderTrackerConfig()
initTracker(CoroutineScope(UnconfinedTestDispatcher(testScheduler)), config)
- mSeekableSliderTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
+ mSliderStateTracker.setState(SliderState.ARROW_HANDLE_MOVES_CONTINUOUSLY)
// WHEN the slider reaches the lower bookend programmatically
val progress = config.upperBookendThreshold + 0.01f
@@ -714,7 +714,7 @@
// THEN the tracker executes upper bookend haptics before moving to IDLE
verify(sliderStateListener).onUpperBookend()
- assertThat(mSeekableSliderTracker.currentState).isEqualTo(SliderState.IDLE)
+ assertThat(mSliderStateTracker.currentState).isEqualTo(SliderState.IDLE)
}
@OptIn(ExperimentalCoroutinesApi::class)
@@ -722,8 +722,8 @@
scope: CoroutineScope,
config: SeekableSliderTrackerConfig = SeekableSliderTrackerConfig(),
) {
- mSeekableSliderTracker =
- SeekableSliderTracker(sliderStateListener, sliderEventProducer, scope, config)
- mSeekableSliderTracker.startTracking()
+ mSliderStateTracker =
+ SliderStateTracker(sliderStateListener, sliderEventProducer, scope, config)
+ mSliderStateTracker.startTracking()
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
index dc7f372..472d045 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/DeviceEntrySideFpsOverlayInteractorTest.kt
@@ -42,7 +42,6 @@
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.testKosmos
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
@@ -86,8 +85,6 @@
@Before
fun setup() {
- mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
-
primaryBouncerInteractor =
PrimaryBouncerInteractor(
bouncerRepository,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index 671b09b..3827046 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -897,6 +897,31 @@
}
@Test
+ fun alternateBouncerToGone() =
+ testScope.runTest {
+ // GIVEN a prior transition has run to ALTERNATE_BOUNCER
+ bouncerRepository.setAlternateVisible(true)
+ runTransitionAndSetWakefulness(
+ KeyguardState.LOCKSCREEN,
+ KeyguardState.ALTERNATE_BOUNCER
+ )
+
+ // GIVEN the keyguard is going away
+ keyguardRepository.setKeyguardGoingAway(true)
+ runCurrent()
+
+ assertThat(transitionRepository)
+ .startedTransition(
+ ownerName = "FromAlternateBouncerTransitionInteractor",
+ from = KeyguardState.ALTERNATE_BOUNCER,
+ to = KeyguardState.GONE,
+ animatorAssertion = { it.isNotNull() },
+ )
+
+ coroutineContext.cancelChildren()
+ }
+
+ @Test
fun alternateBouncerToGlanceableHub() =
testScope.runTest {
// GIVEN a prior transition has run to ALTERNATE_BOUNCER
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
index 8004c6d..ff712ad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetAdapterTest.java
@@ -20,10 +20,12 @@
import androidx.test.filters.SmallTest;
-import com.android.systemui.res.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.res.R;
import com.android.wifitrackerlib.WifiEntry;
+import kotlinx.coroutines.CoroutineScope;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -50,6 +52,8 @@
public MockitoRule mRule = MockitoJUnit.rule();
@Spy
private Context mSpyContext = mContext;
+ @Mock
+ CoroutineScope mScope;
@Mock
private WifiEntry mInternetWifiEntry;
@@ -81,7 +85,7 @@
when(mWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
when(mWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
- mInternetAdapter = new InternetAdapter(mInternetDialogController);
+ mInternetAdapter = new InternetAdapter(mInternetDialogController, mScope);
mViewHolder = mInternetAdapter.onCreateViewHolder(new LinearLayout(mContext), 0);
mInternetAdapter.setWifiEntries(Arrays.asList(mWifiEntry), 1 /* wifiEntriesCount */);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java
index db9f5cf..6f88891 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogDelegateTest.java
@@ -1,7 +1,9 @@
package com.android.systemui.qs.tiles.dialog;
import static com.android.systemui.qs.tiles.dialog.InternetDialogController.MAX_WIFI_ENTRY_COUNT;
+
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -38,6 +40,8 @@
import com.android.systemui.util.time.FakeSystemClock;
import com.android.wifitrackerlib.WifiEntry;
+import kotlinx.coroutines.CoroutineScope;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
@@ -64,6 +68,8 @@
@Mock
private Handler mHandler;
@Mock
+ CoroutineScope mScope;
+ @Mock
private TelephonyManager mTelephonyManager;
@Mock
private WifiEntry mInternetWifiEntry;
@@ -133,6 +139,7 @@
true,
true,
true,
+ mScope,
mock(UiEventLogger.class),
mDialogTransitionAnimator,
mHandler,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
index 6a22d86..fb91c78 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
@@ -24,7 +24,7 @@
import com.android.settingslib.RestrictedLockUtils
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingManagerFake
-import com.android.systemui.haptics.slider.SeekableSliderHapticPlugin
+import com.android.systemui.haptics.slider.SeekbarHapticPlugin
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.policy.BrightnessMirrorController
@@ -93,7 +93,7 @@
brightnessSliderView,
mFalsingManager,
uiEventLogger,
- SeekableSliderHapticPlugin(vibratorHelper, systemClock),
+ SeekbarHapticPlugin(vibratorHelper, systemClock),
activityStarter,
)
mController.init()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
index fd9daf8..03f5ecf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
@@ -25,23 +25,24 @@
import android.view.View
import android.view.WindowManager
import android.widget.FrameLayout
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
+import com.android.systemui.ambient.touch.TouchHandler
+import com.android.systemui.ambient.touch.TouchMonitor
+import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent
import com.android.systemui.communal.data.repository.FakeCommunalRepository
import com.android.systemui.communal.data.repository.fakeCommunalRepository
-import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.communal.domain.interactor.communalInteractor
import com.android.systemui.communal.domain.interactor.setCommunalAvailable
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
import com.android.systemui.communal.util.CommunalColors
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -51,7 +52,6 @@
import com.android.systemui.res.R
import com.android.systemui.scene.shared.model.sceneDataSourceDelegator
import com.android.systemui.shade.data.repository.fakeShadeRepository
-import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.statusbar.phone.SystemUIDialogFactory
import com.android.systemui.testKosmos
@@ -60,7 +60,6 @@
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Assert.assertThrows
@@ -87,16 +86,14 @@
@Mock private lateinit var communalViewModel: CommunalViewModel
@Mock private lateinit var powerManager: PowerManager
@Mock private lateinit var dialogFactory: SystemUIDialogFactory
+ @Mock private lateinit var touchMonitor: TouchMonitor
@Mock private lateinit var communalColors: CommunalColors
- private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
- private lateinit var shadeInteractor: ShadeInteractor
- private lateinit var keyguardInteractor: KeyguardInteractor
+ private lateinit var ambientTouchComponentFactory: AmbientTouchComponent.Factory
private lateinit var parentView: FrameLayout
private lateinit var containerView: View
private lateinit var testableLooper: TestableLooper
- private lateinit var communalInteractor: CommunalInteractor
private lateinit var communalRepository: FakeCommunalRepository
private lateinit var underTest: GlanceableHubContainerController
@@ -104,32 +101,37 @@
fun setUp() {
MockitoAnnotations.initMocks(this)
- communalInteractor = kosmos.communalInteractor
communalRepository = kosmos.fakeCommunalRepository
- keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor
- keyguardInteractor = kosmos.keyguardInteractor
- shadeInteractor = kosmos.shadeInteractor
- underTest =
- GlanceableHubContainerController(
- communalInteractor,
- communalViewModel,
- dialogFactory,
- keyguardTransitionInteractor,
- keyguardInteractor,
- shadeInteractor,
- powerManager,
- communalColors,
- kosmos.sceneDataSourceDelegator,
- )
+ ambientTouchComponentFactory =
+ object : AmbientTouchComponent.Factory {
+ override fun create(
+ lifecycleOwner: LifecycleOwner,
+ touchHandlers: Set<TouchHandler>
+ ): AmbientTouchComponent =
+ object : AmbientTouchComponent {
+ override fun getTouchMonitor(): TouchMonitor = touchMonitor
+ }
+ }
+
+ with(kosmos) {
+ underTest =
+ GlanceableHubContainerController(
+ communalInteractor,
+ communalViewModel,
+ dialogFactory,
+ keyguardTransitionInteractor,
+ keyguardInteractor,
+ shadeInteractor,
+ powerManager,
+ communalColors,
+ ambientTouchComponentFactory,
+ kosmos.sceneDataSourceDelegator,
+ )
+ }
testableLooper = TestableLooper.get(this)
overrideResource(R.dimen.communal_right_edge_swipe_region_width, RIGHT_SWIPE_REGION_WIDTH)
- overrideResource(R.dimen.communal_top_edge_swipe_region_height, TOP_SWIPE_REGION_WIDTH)
- overrideResource(
- R.dimen.communal_bottom_edge_swipe_region_height,
- BOTTOM_SWIPE_REGION_WIDTH
- )
// Make communal available so that communalInteractor.desiredScene accurately reflects
// scene changes instead of just returning Blank.
@@ -161,6 +163,7 @@
shadeInteractor,
powerManager,
communalColors,
+ ambientTouchComponentFactory,
kosmos.sceneDataSourceDelegator,
)
@@ -215,62 +218,6 @@
}
@Test
- fun onTouchEvent_topSwipeWhenCommunalOpen_doesNotIntercept() =
- with(kosmos) {
- testScope.runTest {
- // Communal is open.
- goToScene(CommunalScenes.Communal)
-
- // Touch event in the top swipe region is not intercepted.
- assertThat(underTest.onTouchEvent(DOWN_IN_TOP_SWIPE_REGION_EVENT)).isFalse()
- }
- }
-
- @Test
- fun onTouchEvent_bottomSwipeWhenCommunalOpen_doesNotIntercept() =
- with(kosmos) {
- testScope.runTest {
- // Communal is open.
- goToScene(CommunalScenes.Communal)
-
- // Touch event in the bottom swipe region is not intercepted.
- assertThat(underTest.onTouchEvent(DOWN_IN_BOTTOM_SWIPE_REGION_EVENT)).isFalse()
- }
- }
-
- @Test
- fun onTouchEvent_topSwipeWhenDreaming_doesNotIntercept() =
- with(kosmos) {
- testScope.runTest {
- // Communal is open.
- goToScene(CommunalScenes.Communal)
-
- // Device is dreaming.
- fakeKeyguardRepository.setDreaming(true)
- runCurrent()
-
- // Touch event in the top swipe region is not intercepted.
- assertThat(underTest.onTouchEvent(DOWN_IN_TOP_SWIPE_REGION_EVENT)).isFalse()
- }
- }
-
- @Test
- fun onTouchEvent_bottomSwipeWhenDreaming_doesNotIntercept() =
- with(kosmos) {
- testScope.runTest {
- // Communal is open.
- goToScene(CommunalScenes.Communal)
-
- // Device is dreaming.
- fakeKeyguardRepository.setDreaming(true)
- runCurrent()
-
- // Touch event in the bottom swipe region is not intercepted.
- assertThat(underTest.onTouchEvent(DOWN_IN_BOTTOM_SWIPE_REGION_EVENT)).isFalse()
- }
- }
-
- @Test
fun onTouchEvent_communalAndBouncerShowing_doesNotIntercept() =
with(kosmos) {
testScope.runTest {
@@ -327,6 +274,141 @@
}
@Test
+ fun lifecycle_initializedAfterConstruction() =
+ with(kosmos) {
+ val underTest =
+ GlanceableHubContainerController(
+ communalInteractor,
+ communalViewModel,
+ dialogFactory,
+ keyguardTransitionInteractor,
+ keyguardInteractor,
+ shadeInteractor,
+ powerManager,
+ communalColors,
+ ambientTouchComponentFactory,
+ kosmos.sceneDataSourceDelegator,
+ )
+
+ assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.INITIALIZED)
+ }
+
+ @Test
+ fun lifecycle_createdAfterViewCreated() =
+ with(kosmos) {
+ val underTest =
+ GlanceableHubContainerController(
+ communalInteractor,
+ communalViewModel,
+ dialogFactory,
+ keyguardTransitionInteractor,
+ keyguardInteractor,
+ shadeInteractor,
+ powerManager,
+ communalColors,
+ ambientTouchComponentFactory,
+ kosmos.sceneDataSourceDelegator,
+ )
+
+ // Only initView without attaching a view as we don't want the flows to start collecting
+ // yet.
+ underTest.initView(View(context))
+
+ assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.CREATED)
+ }
+
+ @Test
+ fun lifecycle_startedAfterFlowsUpdate() {
+ // Flows start collecting due to test setup, causing the state to advance to STARTED.
+ assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED)
+ }
+
+ @Test
+ fun lifecycle_resumedAfterCommunalShows() {
+ // Communal is open.
+ goToScene(CommunalScenes.Communal)
+
+ assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.RESUMED)
+ }
+
+ @Test
+ fun lifecycle_startedAfterCommunalCloses() =
+ with(kosmos) {
+ testScope.runTest {
+ // Communal is open.
+ goToScene(CommunalScenes.Communal)
+
+ assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.RESUMED)
+
+ // Communal closes.
+ goToScene(CommunalScenes.Blank)
+
+ assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED)
+ }
+ }
+
+ @Test
+ fun lifecycle_startedAfterPrimaryBouncerShows() =
+ with(kosmos) {
+ testScope.runTest {
+ // Communal is open.
+ goToScene(CommunalScenes.Communal)
+
+ // Bouncer is visible.
+ fakeKeyguardTransitionRepository.sendTransitionSteps(
+ KeyguardState.GLANCEABLE_HUB,
+ KeyguardState.PRIMARY_BOUNCER,
+ testScope
+ )
+ testableLooper.processAllMessages()
+
+ assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED)
+ }
+ }
+
+ @Test
+ fun lifecycle_startedAfterAlternateBouncerShows() =
+ with(kosmos) {
+ testScope.runTest {
+ // Communal is open.
+ goToScene(CommunalScenes.Communal)
+
+ // Bouncer is visible.
+ fakeKeyguardTransitionRepository.sendTransitionSteps(
+ KeyguardState.GLANCEABLE_HUB,
+ KeyguardState.ALTERNATE_BOUNCER,
+ testScope
+ )
+ testableLooper.processAllMessages()
+
+ assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED)
+ }
+ }
+
+ @Test
+ fun lifecycle_createdAfterDisposeView() {
+ // Container view disposed.
+ underTest.disposeView()
+
+ assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.CREATED)
+ }
+
+ @Test
+ fun lifecycle_startedAfterShadeShows() =
+ with(kosmos) {
+ testScope.runTest {
+ // Communal is open.
+ goToScene(CommunalScenes.Communal)
+
+ // Shade shows up.
+ fakeShadeRepository.setQsExpansion(1.0f)
+ testableLooper.processAllMessages()
+
+ assertThat(underTest.lifecycle.currentState).isEqualTo(Lifecycle.State.STARTED)
+ }
+ }
+
+ @Test
fun editMode_communalAvailable() =
with(kosmos) {
testScope.runTest {
@@ -371,8 +453,6 @@
private const val CONTAINER_WIDTH = 100
private const val CONTAINER_HEIGHT = 100
private const val RIGHT_SWIPE_REGION_WIDTH = 20
- private const val TOP_SWIPE_REGION_WIDTH = 20
- private const val BOTTOM_SWIPE_REGION_WIDTH = 20
/**
* A touch down event right in the middle of the screen, to avoid being in any of the swipe
@@ -389,17 +469,6 @@
)
private val DOWN_IN_RIGHT_SWIPE_REGION_EVENT =
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, CONTAINER_WIDTH.toFloat(), 0f, 0)
- private val DOWN_IN_TOP_SWIPE_REGION_EVENT =
- MotionEvent.obtain(
- 0L,
- 0L,
- MotionEvent.ACTION_DOWN,
- 0f,
- TOP_SWIPE_REGION_WIDTH.toFloat(),
- 0
- )
- private val DOWN_IN_BOTTOM_SWIPE_REGION_EVENT =
- MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, CONTAINER_HEIGHT.toFloat(), 0)
private val MOVE_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, 0f, 0)
private val UP_EVENT = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
index da09579..d95cc2e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
@@ -500,6 +500,46 @@
}
@Test
+ fun handleExternalTouch_intercepted_sendsOnTouch() {
+ // Accept dispatch and also intercept.
+ whenever(view.dispatchTouchEvent(any())).thenReturn(true)
+ whenever(view.onInterceptTouchEvent(any())).thenReturn(true)
+
+ underTest.handleExternalTouch(DOWN_EVENT)
+ underTest.handleExternalTouch(MOVE_EVENT)
+
+ // Once intercepted, both events are sent to the view.
+ verify(view).onTouchEvent(DOWN_EVENT)
+ verify(view).onTouchEvent(MOVE_EVENT)
+ }
+
+ @Test
+ fun handleExternalTouch_notDispatched_interceptNotCalled() {
+ // Don't accept dispatch
+ whenever(view.dispatchTouchEvent(any())).thenReturn(false)
+
+ underTest.handleExternalTouch(DOWN_EVENT)
+
+ // Interception is not offered.
+ verify(view, never()).onInterceptTouchEvent(any())
+ }
+
+ @Test
+ fun handleExternalTouch_notIntercepted_onTouchNotSent() {
+ // Accept dispatch, but don't dispatch
+ whenever(view.dispatchTouchEvent(any())).thenReturn(true)
+ whenever(view.onInterceptTouchEvent(any())).thenReturn(false)
+
+ underTest.handleExternalTouch(DOWN_EVENT)
+ underTest.handleExternalTouch(MOVE_EVENT)
+
+ // Interception offered for both events, but onTouchEvent is never called.
+ verify(view).onInterceptTouchEvent(DOWN_EVENT)
+ verify(view).onInterceptTouchEvent(MOVE_EVENT)
+ verify(view, never()).onTouchEvent(any())
+ }
+
+ @Test
fun testGetKeyguardMessageArea() =
testScope.runTest {
underTest.keyguardMessageArea
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 3a427f3..a66a136 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -76,6 +76,7 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.ColorUpdateLogger;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider;
@@ -127,6 +128,7 @@
@Mock private NotificationGutsManager mNotificationGutsManager;
@Mock private NotificationsController mNotificationsController;
@Mock private NotificationVisibilityProvider mVisibilityProvider;
+ @Mock private NotificationWakeUpCoordinator mNotificationWakeUpCoordinator;
@Mock private HeadsUpManager mHeadsUpManager;
@Mock private NotificationRoundnessManager mNotificationRoundnessManager;
@Mock private TunerService mTunerService;
@@ -927,6 +929,7 @@
mNotificationGutsManager,
mNotificationsController,
mVisibilityProvider,
+ mNotificationWakeUpCoordinator,
mHeadsUpManager,
mNotificationRoundnessManager,
mTunerService,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt
index 64f19b6..8eea29b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/DeviceBasedSatelliteViewModelTest.kt
@@ -21,11 +21,13 @@
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.log.core.FakeLogBuffer
+import com.android.systemui.res.R
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.satellite.data.prod.FakeDeviceBasedSatelliteRepository
import com.android.systemui.statusbar.pipeline.satellite.domain.interactor.DeviceBasedSatelliteInteractor
+import com.android.systemui.statusbar.pipeline.satellite.shared.model.SatelliteConnectionState
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl
@@ -76,7 +78,8 @@
)
underTest =
- DeviceBasedSatelliteViewModel(
+ DeviceBasedSatelliteViewModelImpl(
+ context,
interactor,
testScope.backgroundScope,
airplaneModeRepository,
@@ -124,6 +127,7 @@
assertThat(latest).isNull()
}
+ @OptIn(ExperimentalCoroutinesApi::class)
@Test
fun icon_nullWhenShouldNotShow_isEmergencyOnly() =
testScope.runTest {
@@ -298,4 +302,313 @@
// THEN icon is set because the device lost wifi connection
assertThat(latest).isInstanceOf(Icon::class.java)
}
+
+ @Test
+ fun carrierText_nullWhenShouldNotShow_satelliteNotAllowed() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.carrierText)
+
+ // GIVEN satellite is not allowed
+ repo.isSatelliteAllowedForCurrentLocation.value = false
+
+ // GIVEN all icons are OOS
+ val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+ i1.isInService.value = false
+ i1.isEmergencyOnly.value = false
+
+ // GIVEN apm is disabled
+ airplaneModeRepository.setIsAirplaneMode(false)
+
+ // THEN carrier text is null because we should not be showing it
+ assertThat(latest).isNull()
+ }
+
+ @Test
+ fun carrierText_nullWhenShouldNotShow_notAllOos() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.carrierText)
+
+ // GIVEN satellite is allowed + connected
+ repo.isSatelliteAllowedForCurrentLocation.value = true
+ repo.connectionState.value = SatelliteConnectionState.Connected
+
+ // GIVEN all icons are not OOS
+ val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+ i1.isInService.value = true
+ i1.isEmergencyOnly.value = false
+
+ // GIVEN apm is disabled
+ airplaneModeRepository.setIsAirplaneMode(false)
+
+ // THEN carrier text is null because we have service
+ assertThat(latest).isNull()
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ fun carrierText_nullWhenShouldNotShow_isEmergencyOnly() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.carrierText)
+
+ // GIVEN satellite is allowed + connected
+ repo.isSatelliteAllowedForCurrentLocation.value = true
+ repo.connectionState.value = SatelliteConnectionState.Connected
+
+ // GIVEN all icons are OOS
+ val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+ i1.isInService.value = false
+ i1.isEmergencyOnly.value = false
+
+ // GIVEN apm is disabled
+ airplaneModeRepository.setIsAirplaneMode(false)
+
+ // Wait for delay to be completed
+ advanceTimeBy(10.seconds)
+
+ // THEN carrier text is set because we don't have service
+ assertThat(latest).isNotNull()
+
+ // GIVEN the connection is emergency only
+ i1.isEmergencyOnly.value = true
+
+ // THEN carrier text is null because we have emergency connection
+ assertThat(latest).isNull()
+ }
+
+ @Test
+ fun carrierText_nullWhenShouldNotShow_apmIsEnabled() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.carrierText)
+
+ // GIVEN satellite is allowed + connected
+ repo.isSatelliteAllowedForCurrentLocation.value = true
+ repo.connectionState.value = SatelliteConnectionState.Connected
+
+ // GIVEN all icons are OOS
+ val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+ i1.isInService.value = false
+ i1.isEmergencyOnly.value = false
+
+ // GIVEN apm is enabled
+ airplaneModeRepository.setIsAirplaneMode(true)
+
+ // THEN carrier text is null because we should not be showing it
+ assertThat(latest).isNull()
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ fun carrierText_satelliteIsOn() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.carrierText)
+
+ // GIVEN satellite is allowed + connected
+ repo.isSatelliteAllowedForCurrentLocation.value = true
+ repo.connectionState.value = SatelliteConnectionState.Connected
+
+ // GIVEN all icons are OOS
+ val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+ i1.isInService.value = false
+ i1.isEmergencyOnly.value = false
+
+ // GIVEN apm is disabled
+ airplaneModeRepository.setIsAirplaneMode(false)
+
+ // Wait for delay to be completed
+ advanceTimeBy(10.seconds)
+
+ // THEN carrier text is set because we don't have service
+ assertThat(latest).isNotNull()
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ fun carrierText_hysteresisWhenEnablingText() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.carrierText)
+
+ // GIVEN satellite is allowed + connected
+ repo.isSatelliteAllowedForCurrentLocation.value = true
+ repo.connectionState.value = SatelliteConnectionState.Connected
+
+ // GIVEN all icons are OOS
+ val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+ i1.isInService.value = false
+ i1.isEmergencyOnly.value = false
+
+ // GIVEN apm is disabled
+ airplaneModeRepository.setIsAirplaneMode(false)
+
+ // THEN carrier text is null because of the hysteresis
+ assertThat(latest).isNull()
+
+ // Wait for delay to be completed
+ advanceTimeBy(10.seconds)
+
+ // THEN carrier text is set after the delay
+ assertThat(latest).isNotNull()
+
+ // GIVEN apm is enabled
+ airplaneModeRepository.setIsAirplaneMode(true)
+
+ // THEN carrier text is null immediately
+ assertThat(latest).isNull()
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ fun carrierText_deviceIsProvisioned() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.carrierText)
+
+ // GIVEN satellite is allowed + connected
+ repo.isSatelliteAllowedForCurrentLocation.value = true
+ repo.connectionState.value = SatelliteConnectionState.Connected
+
+ // GIVEN all icons are OOS
+ val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+ i1.isInService.value = false
+ i1.isEmergencyOnly.value = false
+
+ // GIVEN apm is disabled
+ airplaneModeRepository.setIsAirplaneMode(false)
+
+ // GIVEN device is not provisioned
+ deviceProvisionedRepository.setDeviceProvisioned(false)
+
+ // THEN carrier text is null because the device is not provisioned
+ assertThat(latest).isNull()
+
+ // GIVEN device becomes provisioned
+ deviceProvisionedRepository.setDeviceProvisioned(true)
+
+ // Wait for delay to be completed
+ advanceTimeBy(10.seconds)
+
+ // THEN carrier text is null because the device is not provisioned
+ assertThat(latest).isNotNull()
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ fun carrierText_wifiIsActive() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.carrierText)
+
+ // GIVEN satellite is allowed + connected
+ repo.isSatelliteAllowedForCurrentLocation.value = true
+ repo.connectionState.value = SatelliteConnectionState.Connected
+
+ // GIVEN all icons are OOS
+ val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+ i1.isInService.value = false
+ i1.isEmergencyOnly.value = false
+
+ // GIVEN apm is disabled
+ airplaneModeRepository.setIsAirplaneMode(false)
+
+ // GIVEN device is provisioned
+ deviceProvisionedRepository.setDeviceProvisioned(true)
+
+ // GIVEN wifi network is active
+ wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 0, level = 1))
+
+ // THEN carrier text is null because the device is connected to wifi
+ assertThat(latest).isNull()
+
+ // GIVEN device loses wifi connection
+ wifiRepository.setWifiNetwork(WifiNetworkModel.Invalid("test"))
+
+ // Wait for delay to be completed
+ advanceTimeBy(10.seconds)
+
+ // THEN carrier text is set because the device lost wifi connection
+ assertThat(latest).isNotNull()
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ fun carrierText_connectionStateUnknown_null() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.carrierText)
+
+ // Set up the conditions for satellite to be enabled
+ repo.isSatelliteAllowedForCurrentLocation.value = true
+ val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+ i1.isInService.value = false
+ i1.isEmergencyOnly.value = false
+ airplaneModeRepository.setIsAirplaneMode(false)
+
+ repo.connectionState.value = SatelliteConnectionState.Unknown
+
+ // Wait for delay to be completed
+ advanceTimeBy(10.seconds)
+
+ assertThat(latest).isNull()
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ fun carrierText_connectionStateOff_null() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.carrierText)
+
+ // Set up the conditions for satellite to be enabled
+ repo.isSatelliteAllowedForCurrentLocation.value = true
+ val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+ i1.isInService.value = false
+ i1.isEmergencyOnly.value = false
+ airplaneModeRepository.setIsAirplaneMode(false)
+
+ repo.connectionState.value = SatelliteConnectionState.Off
+
+ // Wait for delay to be completed
+ advanceTimeBy(10.seconds)
+
+ assertThat(latest).isNull()
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ fun carrierText_connectionStateOn_notConnectedString() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.carrierText)
+
+ // Set up the conditions for satellite to be enabled
+ repo.isSatelliteAllowedForCurrentLocation.value = true
+ val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+ i1.isInService.value = false
+ i1.isEmergencyOnly.value = false
+ airplaneModeRepository.setIsAirplaneMode(false)
+
+ repo.connectionState.value = SatelliteConnectionState.On
+
+ // Wait for delay to be completed
+ advanceTimeBy(10.seconds)
+
+ assertThat(latest)
+ .isEqualTo(context.getString(R.string.satellite_not_connected_carrier_text))
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ fun carrierText_connectionStateConnected_connectedString() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.carrierText)
+
+ // Set up the conditions for satellite to be enabled
+ repo.isSatelliteAllowedForCurrentLocation.value = true
+ val i1 = mobileIconsInteractor.getMobileConnectionInteractorForSubId(1)
+ i1.isInService.value = false
+ i1.isEmergencyOnly.value = false
+ airplaneModeRepository.setIsAirplaneMode(false)
+
+ repo.connectionState.value = SatelliteConnectionState.Connected
+
+ // Wait for delay to be completed
+ advanceTimeBy(10.seconds)
+
+ assertThat(latest)
+ .isEqualTo(context.getString(R.string.satellite_connected_carrier_text))
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/FakeDeviceBasedSatelliteViewModel.kt
similarity index 62%
copy from packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
copy to packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/FakeDeviceBasedSatelliteViewModel.kt
index c4476fc..f125ef12 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/satellite/ui/viewmodel/FakeDeviceBasedSatelliteViewModel.kt
@@ -14,11 +14,12 @@
* limitations under the License.
*/
-package com.android.systemui.volume.panel.component.mediaoutput.shared.model
+package com.android.systemui.statusbar.pipeline.satellite.ui.viewmodel
-import android.media.session.PlaybackState
+import com.android.systemui.common.shared.model.Icon
+import kotlinx.coroutines.flow.MutableStateFlow
-data class SessionWithPlayback(
- val session: MediaDeviceSession,
- val playback: PlaybackState,
-)
+class FakeDeviceBasedSatelliteViewModel : DeviceBasedSatelliteViewModel {
+ override val icon = MutableStateFlow<Icon?>(null)
+ override val carrierText = MutableStateFlow<String?>(null)
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt
index 8a95136..65eb338 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt
@@ -20,6 +20,7 @@
import android.graphics.Point
import com.android.systemui.biometrics.shared.model.LockoutMode
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.shared.model.DevicePosture
import dagger.Binds
import dagger.Module
import javax.inject.Inject
@@ -42,6 +43,8 @@
override val cameraInfo: StateFlow<CameraInfo?>
get() = currentCameraInfo
+ override val supportedPostures: List<DevicePosture> = listOf(DevicePosture.CLOSED)
+
fun setLockoutMode(userId: Int, mode: LockoutMode) {
lockoutModesForUser[userId] = mode
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/BluetoothAdapterKosmos.kt
similarity index 71%
copy from packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/BluetoothAdapterKosmos.kt
index c4476fc..854548c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/BluetoothAdapterKosmos.kt
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.volume.panel.component.mediaoutput.shared.model
+package com.android.systemui.bluetooth
-import android.media.session.PlaybackState
+import android.bluetooth.BluetoothAdapter
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
-data class SessionWithPlayback(
- val session: MediaDeviceSession,
- val playback: PlaybackState,
-)
+var Kosmos.bluetoothAdapter: BluetoothAdapter by Kosmos.Fixture { mock {} }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/CachedBluetoothDeviceManagerKosmos.kt
similarity index 67%
copy from packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/CachedBluetoothDeviceManagerKosmos.kt
index c4476fc..07f0995 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/CachedBluetoothDeviceManagerKosmos.kt
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.volume.panel.component.mediaoutput.shared.model
+package com.android.systemui.bluetooth
-import android.media.session.PlaybackState
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
-data class SessionWithPlayback(
- val session: MediaDeviceSession,
- val playback: PlaybackState,
-)
+var Kosmos.cachedBluetoothDeviceManager: CachedBluetoothDeviceManager by Kosmos.Fixture { mock {} }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/LocalBluetoothManagerKosmos.kt
similarity index 63%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/LocalBluetoothManagerKosmos.kt
index 5e1f85c..eef89e7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bluetooth/LocalBluetoothManagerKosmos.kt
@@ -14,11 +14,14 @@
* limitations under the License.
*/
-package com.android.systemui.volume
+package com.android.systemui.bluetooth
-import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
+import com.android.settingslib.bluetooth.LocalBluetoothManager
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.volume.data.repository.FakeAudioRepository
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
-val Kosmos.audioRepository by Kosmos.Fixture { FakeAudioRepository() }
-val Kosmos.audioModeInteractor by Kosmos.Fixture { AudioModeInteractor(audioRepository) }
+var Kosmos.localBluetoothManager: LocalBluetoothManager? by
+ Kosmos.Fixture {
+ mock { whenever(cachedDeviceManager).thenReturn(cachedBluetoothDeviceManager) }
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt
index 8010261..4e3cbae 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/data/repository/FakeKeyguardBouncerRepository.kt
@@ -1,6 +1,5 @@
package com.android.systemui.bouncer.data.repository
-import com.android.systemui.biometrics.shared.SideFpsControllerRefactor
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants
import com.android.systemui.bouncer.shared.model.BouncerDismissActionModel
import com.android.systemui.bouncer.shared.model.BouncerShowMessageModel
@@ -11,7 +10,6 @@
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
@@ -52,8 +50,6 @@
override var lastAlternateBouncerVisibleTime: Long = 0L
private val _isAlternateBouncerUIAvailable = MutableStateFlow<Boolean>(false)
override val alternateBouncerUIAvailable = _isAlternateBouncerUIAvailable.asStateFlow()
- private val _sideFpsShowing: MutableStateFlow<Boolean> = MutableStateFlow(false)
- override val sideFpsShowing: StateFlow<Boolean> = _sideFpsShowing.asStateFlow()
override var bouncerDismissActionModel: BouncerDismissActionModel? = null
override fun setPrimaryScrimmed(isScrimmed: Boolean) {
@@ -115,12 +111,6 @@
override fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean) {
_isBackButtonEnabled.value = isBackButtonEnabled
}
-
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- override fun setSideFpsShowing(isShowing: Boolean) {
- SideFpsControllerRefactor.assertInLegacyMode()
- _sideFpsShowing.value = isShowing
- }
}
@Module
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt
index 4ed6fe2..329c0f1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/data/repository/FakeCommunalWidgetRepository.kt
@@ -46,6 +46,10 @@
_communalWidgets.value = _communalWidgets.value.filter { it.appWidgetId != widgetId }
}
+ override fun restoreWidgets(oldToNewWidgetIdMap: Map<Int, Int>) {}
+
+ override fun abortRestoreWidgets() {}
+
private fun onConfigured(id: Int, providerInfo: AppWidgetProviderInfo, priority: Int) {
_communalWidgets.value += listOf(CommunalWidgetContentModel(id, providerInfo, priority))
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/doze/DozeLogKosmos.kt
similarity index 72%
copy from packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/doze/DozeLogKosmos.kt
index c4476fc..c54e9d6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/doze/DozeLogKosmos.kt
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.volume.panel.component.mediaoutput.shared.model
+package com.android.systemui.doze
-import android.media.session.PlaybackState
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.util.mockito.mock
-data class SessionWithPlayback(
- val session: MediaDeviceSession,
- val playback: PlaybackState,
-)
+val Kosmos.dozeLog: DozeLog by Fixture { mock<DozeLog>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerFlagParameterization.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerFlagParameterization.kt
index 4e24233..e2a1fe4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerFlagParameterization.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/flags/SceneContainerFlagParameterization.kt
@@ -58,3 +58,8 @@
*/
fun List<FlagsParameterization>.andSceneContainer(): List<FlagsParameterization> =
flatMap { it.andSceneContainer() }.toList()
+
+/** Parameterizes only the scene container flag. */
+fun parameterizeSceneContainerFlag(): List<FlagsParameterization> {
+ return FlagsParameterization.allCombinationsOf().andSceneContainer()
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/DozeInteractorKosmos.kt
similarity index 62%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/DozeInteractorKosmos.kt
index 5e1f85c..3304d44 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/DozeInteractorKosmos.kt
@@ -14,11 +14,16 @@
* limitations under the License.
*/
-package com.android.systemui.volume
+package com.android.systemui.keyguard.domain.interactor
-import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
+import com.android.systemui.keyguard.data.repository.keyguardRepository
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.volume.data.repository.FakeAudioRepository
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.scene.domain.interactor.sceneInteractor
-val Kosmos.audioRepository by Kosmos.Fixture { FakeAudioRepository() }
-val Kosmos.audioModeInteractor by Kosmos.Fixture { AudioModeInteractor(audioRepository) }
+val Kosmos.dozeInteractor: DozeInteractor by Fixture {
+ DozeInteractor(
+ keyguardRepository,
+ { sceneInteractor },
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelKosmos.kt
index 298c70d..00741eb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToGlanceableHubTransitionViewModelKosmos.kt
@@ -17,7 +17,6 @@
package com.android.systemui.keyguard.ui.viewmodel
import com.android.systemui.common.ui.domain.interactor.configurationInteractor
-import com.android.systemui.keyguard.domain.interactor.fromDreamingTransitionInteractor
import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
import com.android.systemui.kosmos.Kosmos
@@ -26,6 +25,5 @@
DreamingToGlanceableHubTransitionViewModel(
configurationInteractor = configurationInteractor,
animationFlow = keyguardTransitionAnimationFlow,
- fromDreamingTransitionInteractor = fromDreamingTransitionInteractor
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt
similarity index 99%
rename from packages/SystemUI/tests/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt
index af785c2..450f08f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/util/KeyguardTransitionRepositorySpySubject.kt
@@ -28,7 +28,7 @@
import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertAbout
import junit.framework.Assert.assertEquals
-import kotlin.test.fail
+import org.junit.Assert.fail
import org.mockito.Mockito
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
index 162f278..d4b7937 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
@@ -22,6 +22,7 @@
import android.os.fakeExecutorHandler
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.bouncerRepository
+import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor
import com.android.systemui.classifier.falsingCollector
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
@@ -30,8 +31,8 @@
import com.android.systemui.communal.domain.interactor.communalInteractor
import com.android.systemui.concurrency.fakeExecutor
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
-import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.globalactions.domain.interactor.globalActionsInteractor
import com.android.systemui.haptics.qs.qsLongPressEffect
import com.android.systemui.jank.interactionJankMonitor
@@ -41,6 +42,7 @@
import com.android.systemui.keyguard.domain.interactor.fromLockscreenTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.fromPrimaryBouncerTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardClockInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.model.sceneContainerPlugin
import com.android.systemui.plugins.statusbar.statusBarStateController
@@ -50,6 +52,8 @@
import com.android.systemui.scene.sceneContainerConfig
import com.android.systemui.scene.shared.model.sceneDataSource
import com.android.systemui.settings.brightness.domain.interactor.brightnessMirrorShowingInteractor
+import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.shade.shadeController
import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
import com.android.systemui.statusbar.phone.screenOffAnimationController
@@ -69,7 +73,6 @@
val testDispatcher by lazy { kosmos.testDispatcher }
val testScope by lazy { kosmos.testScope }
- val fakeFeatureFlags by lazy { kosmos.fakeFeatureFlagsClassic }
val fakeExecutor by lazy { kosmos.fakeExecutor }
val fakeExecutorHandler by lazy { kosmos.fakeExecutorHandler }
val configurationRepository by lazy { kosmos.fakeConfigurationRepository }
@@ -77,6 +80,8 @@
val bouncerRepository by lazy { kosmos.bouncerRepository }
val communalRepository by lazy { kosmos.fakeCommunalRepository }
val keyguardRepository by lazy { kosmos.fakeKeyguardRepository }
+ val keyguardBouncerRepository by lazy { kosmos.fakeKeyguardBouncerRepository }
+ val keyguardInteractor by lazy { kosmos.keyguardInteractor }
val keyguardTransitionRepository by lazy { kosmos.fakeKeyguardTransitionRepository }
val keyguardTransitionInteractor by lazy { kosmos.keyguardTransitionInteractor }
val powerRepository by lazy { kosmos.fakePowerRepository }
@@ -91,6 +96,7 @@
val falsingCollector by lazy { kosmos.falsingCollector }
val powerInteractor by lazy { kosmos.powerInteractor }
val deviceEntryInteractor by lazy { kosmos.deviceEntryInteractor }
+ val deviceEntryUdfpsInteractor by lazy { kosmos.deviceEntryUdfpsInteractor }
val deviceUnlockedInteractor by lazy { kosmos.deviceUnlockedInteractor }
val communalInteractor by lazy { kosmos.communalInteractor }
val sceneContainerPlugin by lazy { kosmos.sceneContainerPlugin }
@@ -110,6 +116,8 @@
val brightnessMirrorShowingInteractor by lazy { kosmos.brightnessMirrorShowingInteractor }
val qsLongPressEffect by lazy { kosmos.qsLongPressEffect }
val shadeController by lazy { kosmos.shadeController }
+ val shadeRepository by lazy { kosmos.shadeRepository }
+ val shadeInteractor by lazy { kosmos.shadeInteractor }
init {
kosmos.applicationContext = testCase.context
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/FakeWindowRootViewComponent.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/FakeWindowRootViewComponent.kt
similarity index 95%
rename from packages/SystemUI/tests/src/com/android/systemui/scene/FakeWindowRootViewComponent.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/scene/FakeWindowRootViewComponent.kt
index 63a05d7..6ac3a62 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/FakeWindowRootViewComponent.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/FakeWindowRootViewComponent.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 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.
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt
index 8f6171d..c7cf934 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneContainerStartableKosmos.kt
@@ -16,6 +16,7 @@
package com.android.systemui.scene.domain.interactor
+import com.android.internal.logging.uiEventLogger
import com.android.systemui.authentication.domain.interactor.authenticationInteractor
import com.android.systemui.bouncer.domain.interactor.bouncerInteractor
import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor
@@ -63,5 +64,6 @@
occlusionInteractor = sceneContainerOcclusionInteractor,
faceUnlockInteractor = deviceEntryFaceAuthInteractor,
shadeInteractor = shadeInteractor,
+ uiEventLogger = uiEventLogger,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
similarity index 71%
copy from packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
index c4476fc..73b775e 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.volume.panel.component.mediaoutput.shared.model
+package com.android.systemui.statusbar
-import android.media.session.PlaybackState
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
-data class SessionWithPlayback(
- val session: MediaDeviceSession,
- val playback: PlaybackState,
-)
+val Kosmos.pulseExpansionHandler: PulseExpansionHandler by
+ Kosmos.Fixture { mock<PulseExpansionHandler>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModelKosmos.kt
index 10cc136..6370a5d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModelKosmos.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.stack.ui.viewmodel
import com.android.systemui.dump.dumpManager
+import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.scene.domain.interactor.sceneInteractor
@@ -29,5 +30,6 @@
stackAppearanceInteractor = notificationStackAppearanceInteractor,
shadeInteractor = shadeInteractor,
sceneInteractor = sceneInteractor,
+ keyguardInteractor = { keyguardInteractor },
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/BiometricUnlockController.kt
similarity index 64%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/BiometricUnlockController.kt
index 5e1f85c..f377e28b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/BiometricUnlockController.kt
@@ -14,11 +14,15 @@
* limitations under the License.
*/
-package com.android.systemui.volume
+@file:OptIn(ExperimentalCoroutinesApi::class)
-import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
+package com.android.systemui.statusbar.phone
+
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.volume.data.repository.FakeAudioRepository
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.util.mockito.mock
+import kotlinx.coroutines.ExperimentalCoroutinesApi
-val Kosmos.audioRepository by Kosmos.Fixture { FakeAudioRepository() }
-val Kosmos.audioModeInteractor by Kosmos.Fixture { AudioModeInteractor(audioRepository) }
+val Kosmos.biometricUnlockController: BiometricUnlockController by Fixture {
+ mock<BiometricUnlockController>()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/DozeScrimController.kt
similarity index 68%
copy from packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/DozeScrimController.kt
index c4476fc..0a1923d 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/DozeScrimController.kt
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.volume.panel.component.mediaoutput.shared.model
+package com.android.systemui.statusbar.phone
-import android.media.session.PlaybackState
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.util.mockito.mock
-data class SessionWithPlayback(
- val session: MediaDeviceSession,
- val playback: PlaybackState,
-)
+val Kosmos.dozeScrimController: DozeScrimController by Fixture { mock<DozeScrimController>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/DozeServiceHostKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/DozeServiceHostKosmos.kt
index 370b177..0b5a68e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/DozeServiceHostKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/DozeServiceHostKosmos.kt
@@ -16,9 +16,45 @@
package com.android.systemui.statusbar.phone
+import android.os.powerManager
+import com.android.keyguard.keyguardUpdateMonitor
+import com.android.systemui.assist.assistManager
+import com.android.systemui.biometrics.authController
+import com.android.systemui.doze.dozeLog
+import com.android.systemui.keyguard.domain.interactor.dozeInteractor
+import com.android.systemui.keyguard.wakefulnessLifecycle
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.plugins.statusbar.statusBarStateController
+import com.android.systemui.shade.domain.interactor.shadeLockscreenInteractor
+import com.android.systemui.statusbar.notificationShadeWindowController
+import com.android.systemui.statusbar.policy.batteryController
+import com.android.systemui.statusbar.policy.deviceProvisionedController
+import com.android.systemui.statusbar.policy.headsUpManager
+import com.android.systemui.statusbar.pulseExpansionHandler
import kotlinx.coroutines.ExperimentalCoroutinesApi
-import org.mockito.Mockito.mock
@OptIn(ExperimentalCoroutinesApi::class)
-val Kosmos.dozeServiceHost: DozeServiceHost by Kosmos.Fixture { mock(DozeServiceHost::class.java) }
+val Kosmos.dozeServiceHost: DozeServiceHost by
+ Kosmos.Fixture {
+ DozeServiceHost(
+ dozeLog,
+ powerManager,
+ wakefulnessLifecycle,
+ statusBarStateController,
+ deviceProvisionedController,
+ headsUpManager,
+ batteryController,
+ scrimController,
+ { biometricUnlockController },
+ { assistManager },
+ dozeScrimController,
+ keyguardUpdateMonitor,
+ pulseExpansionHandler,
+ notificationShadeWindowController,
+ notificationWakeUpCoordinator,
+ authController,
+ notificationIconAreaController,
+ shadeLockscreenInteractor,
+ dozeInteractor,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/NotificationWakeUpCoordinator.kt
similarity index 65%
copy from packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/NotificationWakeUpCoordinator.kt
index 5e1f85c..0c0f87b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/phone/NotificationWakeUpCoordinator.kt
@@ -14,11 +14,13 @@
* limitations under the License.
*/
-package com.android.systemui.volume
+package com.android.systemui.statusbar.phone
-import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.volume.data.repository.FakeAudioRepository
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
+import com.android.systemui.util.mockito.mock
-val Kosmos.audioRepository by Kosmos.Fixture { FakeAudioRepository() }
-val Kosmos.audioModeInteractor by Kosmos.Fixture { AudioModeInteractor(audioRepository) }
+val Kosmos.notificationWakeUpCoordinator: NotificationWakeUpCoordinator by Fixture {
+ mock<NotificationWakeUpCoordinator>()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/BatteryControllerKosmos.kt
similarity index 68%
copy from packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/BatteryControllerKosmos.kt
index c4476fc..b31a45c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/BatteryControllerKosmos.kt
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.volume.panel.component.mediaoutput.shared.model
+package com.android.systemui.statusbar.policy
-import android.media.session.PlaybackState
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import com.android.systemui.util.mockito.mock
-data class SessionWithPlayback(
- val session: MediaDeviceSession,
- val playback: PlaybackState,
-)
+val Kosmos.batteryController: BatteryController by Fixture { mock<BatteryController>() }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/AudioRepositoryKosmos.kt
similarity index 72%
copy from packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/AudioRepositoryKosmos.kt
index c4476fc..5cf214a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/AudioRepositoryKosmos.kt
@@ -14,11 +14,8 @@
* limitations under the License.
*/
-package com.android.systemui.volume.panel.component.mediaoutput.shared.model
+package com.android.systemui.volume.data.repository
-import android.media.session.PlaybackState
+import com.android.systemui.kosmos.Kosmos
-data class SessionWithPlayback(
- val session: MediaDeviceSession,
- val playback: PlaybackState,
-)
+val Kosmos.audioRepository by Kosmos.Fixture { FakeAudioRepository() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt
index 4788624..617fc52 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt
@@ -30,16 +30,14 @@
class FakeAudioRepository : AudioRepository {
private val mutableMode = MutableStateFlow(0)
- override val mode: StateFlow<Int>
- get() = mutableMode.asStateFlow()
+ override val mode: StateFlow<Int> = mutableMode.asStateFlow()
private val mutableRingerMode = MutableStateFlow(RingerMode(0))
- override val ringerMode: StateFlow<RingerMode>
- get() = mutableRingerMode.asStateFlow()
+ override val ringerMode: StateFlow<RingerMode> = mutableRingerMode.asStateFlow()
private val mutableCommunicationDevice = MutableStateFlow<AudioDeviceInfo?>(null)
- override val communicationDevice: StateFlow<AudioDeviceInfo?>
- get() = mutableCommunicationDevice.asStateFlow()
+ override val communicationDevice: StateFlow<AudioDeviceInfo?> =
+ mutableCommunicationDevice.asStateFlow()
private val models: MutableMap<AudioStream, MutableStateFlow<AudioStreamModel>> = mutableMapOf()
private val lastAudibleVolumes: MutableMap<AudioStream, Int> = mutableMapOf()
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioModeInteractorKosmos.kt
similarity index 81%
rename from packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt
rename to packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioModeInteractorKosmos.kt
index 5e1f85c..99354be 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/VolumeKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioModeInteractorKosmos.kt
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.volume
+package com.android.systemui.volume.domain.interactor
import com.android.settingslib.volume.domain.interactor.AudioModeInteractor
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.volume.data.repository.FakeAudioRepository
+import com.android.systemui.volume.data.repository.audioRepository
-val Kosmos.audioRepository by Kosmos.Fixture { FakeAudioRepository() }
val Kosmos.audioModeInteractor by Kosmos.Fixture { AudioModeInteractor(audioRepository) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorKosmos.kt
new file mode 100644
index 0000000..1b18ff5
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorKosmos.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 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.volume.domain.interactor
+
+import com.android.systemui.bluetooth.bluetoothAdapter
+import com.android.systemui.bluetooth.localBluetoothManager
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.volume.data.repository.audioRepository
+import com.android.systemui.volume.localMediaRepositoryFactory
+import com.android.systemui.volume.mediaOutputInteractor
+
+val Kosmos.audioOutputInteractor by
+ Kosmos.Fixture {
+ AudioOutputInteractor(
+ audioRepository,
+ audioModeInteractor,
+ testScope.backgroundScope,
+ testScope.testScheduler,
+ localBluetoothManager,
+ bluetoothAdapter,
+ deviceIconInteractor,
+ mediaOutputInteractor,
+ localMediaRepositoryFactory,
+ )
+ }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/DeviceIconInteractorKosmos.kt
similarity index 70%
copy from packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
copy to packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/DeviceIconInteractorKosmos.kt
index c4476fc..0a27c2a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/shared/model/SessionWithPlayback.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/domain/interactor/DeviceIconInteractorKosmos.kt
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.volume.panel.component.mediaoutput.shared.model
+package com.android.systemui.volume.domain.interactor
-import android.media.session.PlaybackState
+import android.content.applicationContext
+import com.android.systemui.kosmos.Kosmos
-data class SessionWithPlayback(
- val session: MediaDeviceSession,
- val playback: PlaybackState,
-)
+var Kosmos.deviceIconInteractor: DeviceIconInteractor by
+ Kosmos.Fixture { DeviceIconInteractor(applicationContext) }
diff --git a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
index 9b4d378..243e224 100644
--- a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
+++ b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt
@@ -266,6 +266,8 @@
android.telephony.ModemActivityInfo
android.telephony.ServiceState
+android.os.connectivity.WifiActivityEnergyInfo
+
com.android.server.LocalServices
com.android.internal.util.BitUtils
diff --git a/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig
index eb2ef29..0448f6d 100644
--- a/services/accessibility/accessibility.aconfig
+++ b/services/accessibility/accessibility.aconfig
@@ -118,6 +118,16 @@
}
flag {
+ name: "manager_avoid_receiver_timeout"
+ namespace: "accessibility"
+ description: "Avoid broadcast receiver timeout by offloading potentially slow operations to the background thread."
+ bug: "333890389"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "pinch_zoom_zero_min_span"
namespace: "accessibility"
description: "Whether to set min span of ScaleGestureDetector to zero."
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index fc0fb5b..ad869a1 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -994,43 +994,10 @@
"context=" + context + ";intent=" + intent);
}
- String action = intent.getAction();
- if (Intent.ACTION_USER_SWITCHED.equals(action)) {
- switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
- } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
- unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
- } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
- removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
- } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
- final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
- if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) {
- synchronized (mLock) {
- restoreEnabledAccessibilityServicesLocked(
- intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
- intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
- intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
- 0));
- }
- } else if (ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(which)) {
- synchronized (mLock) {
- restoreLegacyDisplayMagnificationNavBarIfNeededLocked(
- intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
- intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
- 0));
- }
- } else if (Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS.equals(which)) {
- synchronized (mLock) {
- restoreAccessibilityButtonTargetsLocked(
- intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
- intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
- }
- } else if (Settings.Secure.ACCESSIBILITY_QS_TARGETS.equals(which)) {
- if (!android.view.accessibility.Flags.a11yQsShortcut()) {
- return;
- }
- restoreAccessibilityQsTargets(
- intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
- }
+ if (com.android.server.accessibility.Flags.managerAvoidReceiverTimeout()) {
+ BackgroundThread.getHandler().post(() -> processBroadcast(intent));
+ } else {
+ processBroadcast(intent);
}
}
}, UserHandle.ALL, intentFilter, null, null);
@@ -2033,6 +2000,19 @@
mA11yWindowManager.onTouchInteractionEnd();
}
+ private void processBroadcast(Intent intent) {
+ String action = intent.getAction();
+ if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+ switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+ } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
+ unlockUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+ } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+ removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+ } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
+ restoreSetting(intent);
+ }
+ }
+
@VisibleForTesting
void switchUser(int userId) {
mMagnificationController.updateUserIdIfNeeded(userId);
@@ -2125,6 +2105,38 @@
getMagnificationController().onUserRemoved(userId);
}
+ private void restoreSetting(Intent intent) {
+ final String which = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
+ if (Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES.equals(which)) {
+ synchronized (mLock) {
+ restoreEnabledAccessibilityServicesLocked(
+ intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
+ intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
+ intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
+ 0));
+ }
+ } else if (ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(which)) {
+ synchronized (mLock) {
+ restoreLegacyDisplayMagnificationNavBarIfNeededLocked(
+ intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE),
+ intent.getIntExtra(Intent.EXTRA_SETTING_RESTORED_FROM_SDK_INT,
+ 0));
+ }
+ } else if (Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS.equals(which)) {
+ synchronized (mLock) {
+ restoreAccessibilityButtonTargetsLocked(
+ intent.getStringExtra(Intent.EXTRA_SETTING_PREVIOUS_VALUE),
+ intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
+ }
+ } else if (Settings.Secure.ACCESSIBILITY_QS_TARGETS.equals(which)) {
+ if (!android.view.accessibility.Flags.a11yQsShortcut()) {
+ return;
+ }
+ restoreAccessibilityQsTargets(
+ intent.getStringExtra(Intent.EXTRA_SETTING_NEW_VALUE));
+ }
+ }
+
// Called only during settings restore; currently supports only the owner user
// TODO: http://b/22388012
void restoreEnabledAccessibilityServicesLocked(String oldSetting, String newSetting,
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 5e566aa..522aa67 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -202,6 +202,7 @@
// Default max API calls per reset interval for generated preview API rate limiting.
private static final int DEFAULT_GENERATED_PREVIEW_MAX_CALLS_PER_INTERVAL = 2;
+ private static final String PENDING_DELETED_IDS_ATTR = "pending_deleted_ids";
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
@@ -228,6 +229,11 @@
onPackageBroadcastReceived(intent, getSendingUserId());
updateWidgetPackageSuspensionMaskedState(intent, false, getSendingUserId());
break;
+ case Intent.ACTION_PACKAGE_RESTARTED:
+ case Intent.ACTION_PACKAGE_UNSTOPPED:
+ if (!android.content.pm.Flags.stayStopped()) return;
+ updateWidgetPackageStoppedMaskedState(intent);
+ break;
default:
onPackageBroadcastReceived(intent, getSendingUserId());
break;
@@ -396,7 +402,10 @@
packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
packageFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
+ packageFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+ packageFilter.addAction(Intent.ACTION_PACKAGE_UNSTOPPED);
packageFilter.addDataScheme("package");
+ packageFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
packageFilter, null, mCallbackHandler);
@@ -581,14 +590,19 @@
changed |= provider.setMaskedByQuietProfileLocked(quietProfile);
try {
boolean suspended;
+ boolean stopped;
try {
suspended = mPackageManager.isPackageSuspendedForUser(
provider.id.componentName.getPackageName(), provider.getUserId());
+ stopped = mPackageManager.isPackageStoppedForUser(
+ provider.id.componentName.getPackageName(), provider.getUserId());
} catch (IllegalArgumentException ex) {
// Package not found.
suspended = false;
+ stopped = false;
}
changed |= provider.setMaskedBySuspendedPackageLocked(suspended);
+ changed |= provider.setMaskedByStoppedPackageLocked(stopped);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to query application info", e);
}
@@ -636,6 +650,82 @@
}
/**
+ * Update the masked state for a stopped or unstopped package.
+ */
+ private void updateWidgetPackageStoppedMaskedState(@NonNull Intent intent) {
+ final int providerUid = intent.getIntExtra(Intent.EXTRA_UID, Process.INVALID_UID);
+ final Uri uri = intent.getData();
+ if (providerUid == Process.INVALID_UID || uri == null) {
+ return;
+ }
+
+ final String packageName = uri.getSchemeSpecificPart();
+ if (packageName == null) {
+ return;
+ }
+
+ boolean isStopped;
+ try {
+ isStopped = mPackageManager.isPackageStoppedForUser(packageName,
+ UserHandle.getUserId(providerUid));
+ } catch (Exception e) {
+ Slog.e(TAG, "Failed to query package stopped state", e);
+ return;
+ }
+
+ if (DEBUG) {
+ Slog.i(TAG, "Updating package stopped masked state for uid " + providerUid + " package "
+ + packageName + " isStopped " + isStopped);
+ }
+ synchronized (mLock) {
+ final int count = mProviders.size();
+ for (int i = 0; i < count; i++) {
+ Provider provider = mProviders.get(i);
+ if (providerUid != provider.id.uid
+ || !packageName.equals(provider.id.componentName.getPackageName())) {
+ continue;
+ }
+ if (provider.setMaskedByStoppedPackageLocked(isStopped)) {
+ if (provider.isMaskedLocked()) {
+ maskWidgetsViewsLocked(provider, null);
+ cancelBroadcastsLocked(provider);
+ } else {
+ unmaskWidgetsViewsLocked(provider);
+ final int widgetCount = provider.widgets.size();
+ if (widgetCount > 0) {
+ final int[] widgetIds = new int[widgetCount];
+ for (int j = 0; j < widgetCount; j++) {
+ widgetIds[j] = provider.widgets.get(j).appWidgetId;
+ }
+ registerForBroadcastsLocked(provider, widgetIds);
+ sendUpdateIntentLocked(provider, widgetIds, /* interactive= */ false);
+ }
+
+ final int pendingIdsCount = provider.pendingDeletedWidgetIds.size();
+ if (pendingIdsCount > 0) {
+ if (DEBUG) {
+ Slog.i(TAG, "Sending missed deleted broadcasts for "
+ + provider.id.componentName + " "
+ + provider.pendingDeletedWidgetIds);
+ }
+ for (int j = 0; j < pendingIdsCount; j++) {
+ sendDeletedIntentLocked(provider.id.componentName,
+ provider.id.getProfile(),
+ provider.pendingDeletedWidgetIds.get(j));
+ }
+ provider.pendingDeletedWidgetIds.clear();
+ if (widgetCount == 0) {
+ sendDisabledIntentLocked(provider);
+ }
+ saveGroupStateAsync(provider.id.getProfile().getIdentifier());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
* Mask the target widget belonging to the specified provider, or all active widgets
* of the provider if target widget == null.
*/
@@ -648,11 +738,11 @@
R.layout.work_widget_mask_view);
ApplicationInfo appInfo = provider.info.providerInfo.applicationInfo;
final int appUserId = provider.getUserId();
- boolean showBadge;
+ boolean showBadge = false;
final long identity = Binder.clearCallingIdentity();
try {
- final Intent onClickIntent;
+ Intent onClickIntent = null;
if (provider.maskedByQuietProfile) {
showBadge = true;
@@ -676,7 +766,7 @@
appInfo.packageName, suspendingPackage, dialogInfo, null, null,
appUserId);
}
- } else /* provider.maskedByLockedProfile */ {
+ } else if (provider.maskedByLockedProfile) {
showBadge = true;
onClickIntent = mKeyguardManager
.createConfirmDeviceCredentialIntent(null, null, appUserId);
@@ -684,6 +774,8 @@
onClickIntent.setFlags(
FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
}
+ } else if (provider.maskedByStoppedPackage) {
+ showBadge = mUserManager.hasBadge(appUserId);
}
Icon icon = appInfo.icon != 0
@@ -697,7 +789,14 @@
for (int j = 0; j < widgetCount; j++) {
Widget widget = provider.widgets.get(j);
if (targetWidget != null && targetWidget != widget) continue;
- if (onClickIntent != null) {
+ if (provider.maskedByStoppedPackage) {
+ Intent intent = createUpdateIntentLocked(provider,
+ new int[] { widget.appWidgetId });
+ views.setOnClickPendingIntent(android.R.id.background,
+ PendingIntent.getBroadcast(mContext, widget.appWidgetId,
+ intent, PendingIntent.FLAG_UPDATE_CURRENT
+ | PendingIntent.FLAG_IMMUTABLE));
+ } else if (onClickIntent != null) {
views.setOnClickPendingIntent(android.R.id.background,
PendingIntent.getActivity(mContext, widget.appWidgetId, onClickIntent,
PendingIntent.FLAG_UPDATE_CURRENT
@@ -1950,15 +2049,23 @@
if (provider != null) {
provider.widgets.remove(widget);
if (!provider.zombie) {
- // send the broacast saying that this appWidgetId has been deleted
- sendDeletedIntentLocked(widget);
+ // If the package is not stopped, send the broadcast saying that this appWidgetId
+ // has been deleted. Otherwise, save the ID and send the broadcast when the package
+ // is unstopped.
+ if (!provider.maskedByStoppedPackage) {
+ sendDeletedIntentLocked(widget);
+ } else {
+ provider.pendingDeletedWidgetIds.add(widget.appWidgetId);
+ }
if (provider.widgets.isEmpty()) {
// cancel the future updates
cancelBroadcastsLocked(provider);
- // send the broacast saying that the provider is not in use any more
- sendDisabledIntentLocked(provider);
+ // send the broadcast saying that the provider is not in use any more
+ if (!provider.maskedByStoppedPackage) {
+ sendDisabledIntentLocked(provider);
+ }
}
}
}
@@ -2033,8 +2140,9 @@
final HashSet<Integer> ids = mRemoteViewsServicesAppWidgets.get(key);
if (ids.remove(widget.appWidgetId)) {
// If we have removed the last app widget referencing this service, then we
- // should destroy it and remove it from this set
- if (ids.isEmpty()) {
+ // should destroy it and remove it from this set. This is skipped for widgets whose
+ // provider is in a stopped package, to avoid waking up the package.
+ if (ids.isEmpty() && !widget.provider.maskedByStoppedPackage) {
destroyRemoteViewsService(key.second.getIntent(), widget);
it.remove();
}
@@ -2544,18 +2652,29 @@
private void sendUpdateIntentLocked(Provider provider, int[] appWidgetIds,
boolean interactive) {
- Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
- intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
- intent.setComponent(provider.id.componentName);
+ Intent intent = createUpdateIntentLocked(provider, appWidgetIds);
sendBroadcastAsUser(intent, provider.id.getProfile(), interactive);
}
+ private Intent createUpdateIntentLocked(Provider provider, int[] appWidgetIds) {
+ Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
+ intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
+ intent.setComponent(provider.id.componentName);
+ return intent;
+ }
+
private void sendDeletedIntentLocked(Widget widget) {
+ sendDeletedIntentLocked(widget.provider.id.componentName, widget.provider.id.getProfile(),
+ widget.appWidgetId);
+ }
+
+ private void sendDeletedIntentLocked(ComponentName provider, UserHandle profile,
+ int appWidgetId) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_DELETED);
- intent.setComponent(widget.provider.id.componentName);
- intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widget.appWidgetId);
+ intent.setComponent(provider);
+ intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
// Cleanup after deletion isn't an interactive UX case
- sendBroadcastAsUser(intent, widget.provider.id.getProfile(), false);
+ sendBroadcastAsUser(intent, profile, false);
}
private void sendDisabledIntentLocked(Provider provider) {
@@ -2684,6 +2803,14 @@
if (persistsProviderInfo && p.mInfoParsed) {
AppWidgetXmlUtil.writeAppWidgetProviderInfoLocked(out, p.info);
}
+ final int pendingIdsCount = p.pendingDeletedWidgetIds.size();
+ if (pendingIdsCount > 0) {
+ final List<String> idStrings = new ArrayList<>();
+ for (int i = 0; i < pendingIdsCount; i++) {
+ idStrings.add(String.valueOf(p.pendingDeletedWidgetIds.get(i)));
+ }
+ out.attribute(null, PENDING_DELETED_IDS_ATTR, String.join(",", idStrings));
+ }
out.endTag(null, "p");
}
@@ -3022,7 +3149,7 @@
continue;
}
- if (provider.widgets.size() > 0) {
+ if (provider.widgets.size() > 0 && !provider.maskedByStoppedPackage) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"appwidget init " + provider.id.componentName.getPackageName());
provider.widgets.forEach(widget -> {
@@ -3440,6 +3567,16 @@
legacyProviderIndex);
provider.tag = providerTag;
provider.infoTag = parser.getAttributeValue(null, "info_tag");
+
+ final String pendingDeletedIds = parser.getAttributeValue(null,
+ PENDING_DELETED_IDS_ATTR);
+ if (pendingDeletedIds != null && !pendingDeletedIds.isEmpty()) {
+ final String[] idStrings = pendingDeletedIds.split(",");
+ for (int i = 0; i < idStrings.length; i++) {
+ provider.pendingDeletedWidgetIds.add(
+ Integer.parseInt(idStrings[i]));
+ }
+ }
} else if ("h".equals(tag)) {
legacyHostIndex++;
Host host = new Host();
@@ -4443,6 +4580,11 @@
boolean maskedByLockedProfile;
boolean maskedByQuietProfile;
boolean maskedBySuspendedPackage;
+ // This provider's package has been stopped
+ boolean maskedByStoppedPackage;
+ // Widget IDs for which we haven't yet sent DELETED broadcasts because the package was
+ // stopped.
+ IntArray pendingDeletedWidgetIds = new IntArray();
boolean mInfoParsed = false;
@@ -4598,8 +4740,15 @@
return masked != oldState;
}
+ public boolean setMaskedByStoppedPackageLocked(boolean masked) {
+ boolean oldState = maskedByStoppedPackage;
+ maskedByStoppedPackage = masked;
+ return masked != oldState;
+ }
+
public boolean isMaskedLocked() {
- return maskedByQuietProfile || maskedByLockedProfile || maskedBySuspendedPackage;
+ return maskedByQuietProfile || maskedByLockedProfile || maskedBySuspendedPackage
+ || maskedByStoppedPackage;
}
public boolean shouldBePersisted() {
diff --git a/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java b/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
index 7f64786..9a73a2d 100644
--- a/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
+++ b/services/contextualsearch/java/com/android/server/contextualsearch/ContextualSearchManagerService.java
@@ -30,7 +30,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static com.android.server.contextualsearch.flags.Flags.enableExcludePersistentUi;
-
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
@@ -65,6 +64,7 @@
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.ShellCallback;
+import android.os.SystemClock;
import android.util.Log;
import android.util.Slog;
import android.view.IWindowManager;
@@ -246,6 +246,9 @@
if (DEBUG_USER) Log.d(TAG, "Launch component: " + launchIntent.getComponent());
launchIntent.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NO_ANIMATION
| FLAG_ACTIVITY_NO_USER_ACTION);
+ launchIntent.putExtra(
+ ContextualSearchManager.EXTRA_INVOCATION_TIME_MS,
+ SystemClock.uptimeMillis());
launchIntent.putExtra(ContextualSearchManager.EXTRA_ENTRYPOINT, entrypoint);
launchIntent.putExtra(ContextualSearchManager.EXTRA_TOKEN, mToken);
boolean isAssistDataAllowed = mAtmInternal.isAssistDataAllowed();
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index 271d552..37c2d26 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -494,10 +494,10 @@
private static void executeRescueLevelInternalOld(Context context, int level, @Nullable
String failedPackage) throws Exception {
- if (level <= LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS) {
- // Disabling flag resets on master branch for trunk stable launch.
- // TODO(b/287618292): Re-enable them after the trunk stable is launched and we
- // figured out a way to reset flags without interfering with trunk development.
+ // Note: DeviceConfig reset is disabled currently and would be enabled using the flag,
+ // after we have figured out a way to reset flags without interfering with trunk
+ // development. TODO: b/287618292 For enabling flag resets.
+ if (!Flags.allowRescuePartyFlagResets() && level <= LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS) {
return;
}
@@ -572,12 +572,16 @@
level, levelToString(level));
switch (level) {
case RESCUE_LEVEL_SCOPED_DEVICE_CONFIG_RESET:
- // Temporary disable deviceConfig reset
- // resetDeviceConfig(context, /*isScoped=*/true, failedPackage);
+ // Enable deviceConfig reset behind flag
+ if (Flags.allowRescuePartyFlagResets()) {
+ resetDeviceConfig(context, /*isScoped=*/true, failedPackage);
+ }
break;
case RESCUE_LEVEL_ALL_DEVICE_CONFIG_RESET:
- // Temporary disable deviceConfig reset
- // resetDeviceConfig(context, /*isScoped=*/false, failedPackage);
+ // Enable deviceConfig reset behind flag
+ if (Flags.allowRescuePartyFlagResets()) {
+ resetDeviceConfig(context, /*isScoped=*/false, failedPackage);
+ }
break;
case RESCUE_LEVEL_WARM_REBOOT:
executeWarmReboot(context, level, failedPackage);
diff --git a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
index 6c7546e..64bca33 100644
--- a/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
+++ b/services/core/java/com/android/server/SensitiveContentProtectionManagerService.java
@@ -17,6 +17,7 @@
package com.android.server;
import static android.permission.flags.Flags.sensitiveContentImprovements;
+import static android.permission.flags.Flags.sensitiveContentMetricsBugfix;
import static android.permission.flags.Flags.sensitiveNotificationAppProtection;
import static android.provider.Settings.Global.DISABLE_SCREEN_SHARE_PROTECTIONS_FOR_APPS_AND_NOTIFICATIONS;
import static android.view.flags.Flags.sensitiveContentAppProtection;
@@ -93,7 +94,7 @@
private boolean mProjectionActive = false;
private static class MediaProjectionSession {
- private final int mUid;
+ private final int mUid; // UID of app that started projection session
private final long mSessionId;
private final boolean mIsExempted;
private final ArraySet<String> mAllSeenNotificationKeys = new ArraySet<>();
@@ -320,6 +321,12 @@
}
mProjectionActive = true;
+
+ if (sensitiveContentMetricsBugfix()) {
+ mWindowManager.setBlockScreenCaptureForAppsSessionId(
+ mMediaProjectionSession.mSessionId);
+ }
+
if (sensitiveNotificationAppProtection()) {
updateAppsThatShouldBlockScreenCapture();
}
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index 1a3ef73..a508ebf 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -106,6 +106,9 @@
// property for runtime configuration differentiation in vendor
private static final String VENDOR_SKU_PROPERTY = "ro.boot.product.vendor.sku";
+ // property for runtime configuration differentation in product
+ private static final String PRODUCT_SKU_PROPERTY = "ro.boot.hardware.sku";
+
private static final ArrayMap<String, ArraySet<String>> EMPTY_PERMISSIONS =
new ArrayMap<>();
@@ -694,6 +697,17 @@
readPermissions(parser, Environment.buildPath(
Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
+ String productSkuProperty = SystemProperties.get(PRODUCT_SKU_PROPERTY, "");
+ if (!productSkuProperty.isEmpty()) {
+ String productSkuDir = "sku_" + productSkuProperty;
+ readPermissions(parser, Environment.buildPath(
+ Environment.getProductDirectory(), "etc", "sysconfig", productSkuDir),
+ productPermissionFlag);
+ readPermissions(parser, Environment.buildPath(
+ Environment.getProductDirectory(), "etc", "permissions", productSkuDir),
+ productPermissionFlag);
+ }
+
// Allow /system_ext to customize all system configs
readPermissions(parser, Environment.buildPath(
Environment.getSystemExtDirectory(), "etc", "sysconfig"), ALLOW_ALL);
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index bd67cf420..e171064 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -425,6 +425,8 @@
private int[] mSCBMReason;
private boolean[] mSCBMStarted;
+ private boolean[] mCarrierRoamingNtnMode = null;
+
/**
* Per-phone map of precise data connection state. The key of the map is the pair of transport
* type and APN setting. This is the cache to prevent redundant callbacks to the listeners.
@@ -723,6 +725,7 @@
mECBMStarted = copyOf(mECBMStarted, mNumPhones);
mSCBMReason = copyOf(mSCBMReason, mNumPhones);
mSCBMStarted = copyOf(mSCBMStarted, mNumPhones);
+ mCarrierRoamingNtnMode = copyOf(mCarrierRoamingNtnMode, mNumPhones);
// ds -> ss switch.
if (mNumPhones < oldNumPhones) {
cutListToSize(mCellInfo, mNumPhones);
@@ -781,6 +784,7 @@
mECBMStarted[i] = false;
mSCBMReason[i] = TelephonyManager.STOP_REASON_UNKNOWN;
mSCBMStarted[i] = false;
+ mCarrierRoamingNtnMode[i] = false;
}
}
}
@@ -854,6 +858,7 @@
mECBMStarted = new boolean[numPhones];
mSCBMReason = new int[numPhones];
mSCBMStarted = new boolean[numPhones];
+ mCarrierRoamingNtnMode = new boolean[numPhones];
for (int i = 0; i < numPhones; i++) {
mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
@@ -897,6 +902,7 @@
mECBMStarted[i] = false;
mSCBMReason[i] = TelephonyManager.STOP_REASON_UNKNOWN;
mSCBMStarted[i] = false;
+ mCarrierRoamingNtnMode[i] = false;
}
mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -1523,6 +1529,14 @@
remove(r.binder);
}
}
+ if (events.contains(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED)) {
+ try {
+ r.callback.onCarrierRoamingNtnModeChanged(
+ mCarrierRoamingNtnMode[r.phoneId]);
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
+ }
}
}
}
@@ -3512,6 +3526,41 @@
handleRemoveListLocked();
}
+ /**
+ * Notify external listeners that carrier roaming non-terrestrial network mode changed.
+ * @param subId subscription ID.
+ * @param active {@code true} If the device is connected to carrier roaming
+ * non-terrestrial network or was connected within the
+ * {CarrierConfigManager#KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT}
+ * duration, {code false} otherwise.
+ */
+ public void notifyCarrierRoamingNtnModeChanged(int subId, boolean active) {
+ if (!checkNotifyPermission("notifyCarrierRoamingNtnModeChanged")) {
+ return;
+ }
+
+ if (VDBG) {
+ log("notifyCarrierRoamingNtnModeChanged: subId=" + subId + " active=" + active);
+ }
+
+ synchronized (mRecords) {
+ int phoneId = getPhoneIdFromSubId(subId);
+ mCarrierRoamingNtnMode[phoneId] = active;
+ for (Record r : mRecords) {
+ if (r.matchTelephonyCallbackEvent(
+ TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED)
+ && idMatch(r, subId, phoneId)) {
+ try {
+ r.callback.onCarrierRoamingNtnModeChanged(active);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
+ }
+ }
+ handleRemoveListLocked();
+ }
+ }
+
@NeverCompile // Avoid size overhead of debugging code.
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index c3a3bf7..eec22c9 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2422,8 +2422,6 @@
getTimeLimitedFgsType(foregroundServiceType);
final TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(timeLimitedFgsType);
if (fgsTypeInfo != null) {
- // TODO(b/330399444): check to see if all time book-keeping for
- // time limited types should use elapsedRealtime instead of uptime
final long before24Hr = Math.max(0,
SystemClock.elapsedRealtime() - (24 * 60 * 60 * 1000));
final long lastTimeOutAt = fgsTypeInfo.getTimeLimitExceededAt();
@@ -3757,7 +3755,7 @@
}
traceInstant("FGS start: ", sr);
- final long nowUptime = SystemClock.uptimeMillis();
+ final long nowRealtime = SystemClock.elapsedRealtime();
// Fetch/create/update the fgs info for the time-limited type.
SparseArray<TimeLimitedFgsInfo> fgsInfo = mTimeLimitedFgsInfo.get(sr.appInfo.uid);
@@ -3768,10 +3766,10 @@
final int timeLimitedFgsType = getTimeLimitedFgsType(sr.foregroundServiceType);
TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(timeLimitedFgsType);
if (fgsTypeInfo == null) {
- fgsTypeInfo = sr.createTimeLimitedFgsInfo(nowUptime);
+ fgsTypeInfo = sr.createTimeLimitedFgsInfo(nowRealtime);
fgsInfo.put(timeLimitedFgsType, fgsTypeInfo);
}
- fgsTypeInfo.setLastFgsStartTime(nowUptime);
+ fgsTypeInfo.setLastFgsStartTime(nowRealtime);
// We'll cancel the previous ANR timer and start a fresh one below.
mFGSAnrTimer.cancel(sr);
@@ -3845,14 +3843,14 @@
final TimeLimitedFgsInfo fgsTypeInfo = fgsInfo.get(fgsType);
if (fgsTypeInfo != null) {
// Update total runtime for the time-limited fgs type and mark it as timed out.
- final long nowUptime = SystemClock.uptimeMillis();
+ final long nowRealtime = SystemClock.elapsedRealtime();
fgsTypeInfo.updateTotalRuntime();
- fgsTypeInfo.setTimeLimitExceededAt(nowUptime);
+ fgsTypeInfo.setTimeLimitExceededAt(nowRealtime);
logFGSStateChangeLocked(sr,
FOREGROUND_SERVICE_STATE_CHANGED__STATE__TIMED_OUT,
- nowUptime > fgsTypeInfo.getLastFgsStartTime()
- ? (int) (nowUptime - fgsTypeInfo.getLastFgsStartTime()) : 0,
+ nowRealtime > fgsTypeInfo.getLastFgsStartTime()
+ ? (int) (nowRealtime - fgsTypeInfo.getLastFgsStartTime()) : 0,
FGS_STOP_REASON_UNKNOWN,
FGS_TYPE_POLICY_CHECK_UNKNOWN,
FOREGROUND_SERVICE_STATE_CHANGED__FGS_START_API__FGSSTARTAPI_NA,
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index f98799d..4f84149 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -133,6 +133,7 @@
import com.android.server.power.stats.PowerStatsStore;
import com.android.server.power.stats.PowerStatsUidResolver;
import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
+import com.android.server.power.stats.WifiPowerStatsProcessor;
import com.android.server.power.stats.wakeups.CpuWakeupStats;
import java.io.File;
@@ -412,6 +413,8 @@
com.android.internal.R.integer.config_defaultPowerStatsThrottlePeriodCpu);
final long powerStatsThrottlePeriodMobileRadio = context.getResources().getInteger(
com.android.internal.R.integer.config_defaultPowerStatsThrottlePeriodMobileRadio);
+ final long powerStatsThrottlePeriodWifi = context.getResources().getInteger(
+ com.android.internal.R.integer.config_defaultPowerStatsThrottlePeriodWifi);
mBatteryStatsConfig =
new BatteryStatsImpl.BatteryStatsConfig.Builder()
.setResetOnUnplugHighBatteryLevel(resetOnUnplugHighBatteryLevel)
@@ -422,6 +425,9 @@
.setPowerStatsThrottlePeriodMillis(
BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
powerStatsThrottlePeriodMobileRadio)
+ .setPowerStatsThrottlePeriodMillis(
+ BatteryConsumer.POWER_COMPONENT_WIFI,
+ powerStatsThrottlePeriodWifi)
.build();
mPowerStatsUidResolver = new PowerStatsUidResolver();
mStats = new BatteryStatsImpl(mBatteryStatsConfig, Clock.SYSTEM_CLOCK, mMonotonicClock,
@@ -480,6 +486,7 @@
AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
.setProcessor(
new CpuPowerStatsProcessor(mPowerProfile, mCpuScalingPolicies));
+
config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
.trackDeviceStates(
AggregatedPowerStatsConfig.STATE_POWER,
@@ -490,9 +497,21 @@
AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
.setProcessor(
new MobileRadioPowerStatsProcessor(mPowerProfile));
+
config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_PHONE,
BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)
.setProcessor(new PhoneCallPowerStatsProcessor());
+
+ config.trackPowerComponent(BatteryConsumer.POWER_COMPONENT_WIFI)
+ .trackDeviceStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN)
+ .trackUidStates(
+ AggregatedPowerStatsConfig.STATE_POWER,
+ AggregatedPowerStatsConfig.STATE_SCREEN,
+ AggregatedPowerStatsConfig.STATE_PROCESS_STATE)
+ .setProcessor(
+ new WifiPowerStatsProcessor(mPowerProfile));
return config;
}
@@ -518,14 +537,22 @@
public void systemServicesReady() {
mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_CPU,
Flags.streamlinedBatteryStats());
- mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
- Flags.streamlinedConnectivityBatteryStats());
mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
BatteryConsumer.POWER_COMPONENT_CPU,
Flags.streamlinedBatteryStats());
+
+ mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
+ Flags.streamlinedConnectivityBatteryStats());
mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
Flags.streamlinedConnectivityBatteryStats());
+
+ mStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_WIFI,
+ Flags.streamlinedConnectivityBatteryStats());
+ mBatteryUsageStatsProvider.setPowerStatsExporterEnabled(
+ BatteryConsumer.POWER_COMPONENT_WIFI,
+ Flags.streamlinedConnectivityBatteryStats());
+
mWorker.systemServicesReady();
mStats.systemServicesReady(mContext);
mCpuWakeupStats.systemServicesReady();
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index fa6b54b..211f952 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -2371,6 +2371,14 @@
return;
}
+ if (opt.shouldNotFreeze()) {
+ if (DEBUG_FREEZER) {
+ Slog.d(TAG_AM, "Skipping freeze because process is marked "
+ + "should not be frozen");
+ }
+ return;
+ }
+
if (pid == 0 || opt.isFrozen()) {
// Already frozen or not a real process, either one being
// launched or one being killed
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 045d137..065f3bd 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -30,9 +30,9 @@
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UptimeMillisLong;
import android.app.BackgroundStartPrivileges;
import android.app.IApplicationThread;
import android.app.Notification;
@@ -677,46 +677,46 @@
* Data container class to help track certain fgs info for time-restricted types.
*/
static class TimeLimitedFgsInfo {
- @UptimeMillisLong
+ @ElapsedRealtimeLong
private long mFirstFgsStartTime;
- @UptimeMillisLong
+ @ElapsedRealtimeLong
private long mLastFgsStartTime;
- @UptimeMillisLong
+ @ElapsedRealtimeLong
private long mTimeLimitExceededAt = Long.MIN_VALUE;
private long mTotalRuntime = 0;
- TimeLimitedFgsInfo(@UptimeMillisLong long startTime) {
+ TimeLimitedFgsInfo(@ElapsedRealtimeLong long startTime) {
mFirstFgsStartTime = startTime;
mLastFgsStartTime = startTime;
}
- @UptimeMillisLong
+ @ElapsedRealtimeLong
public long getFirstFgsStartTime() {
return mFirstFgsStartTime;
}
- public void setLastFgsStartTime(@UptimeMillisLong long startTime) {
+ public void setLastFgsStartTime(@ElapsedRealtimeLong long startTime) {
mLastFgsStartTime = startTime;
}
- @UptimeMillisLong
+ @ElapsedRealtimeLong
public long getLastFgsStartTime() {
return mLastFgsStartTime;
}
public void updateTotalRuntime() {
- mTotalRuntime += SystemClock.uptimeMillis() - mLastFgsStartTime;
+ mTotalRuntime += SystemClock.elapsedRealtime() - mLastFgsStartTime;
}
public long getTotalRuntime() {
return mTotalRuntime;
}
- public void setTimeLimitExceededAt(@UptimeMillisLong long timeLimitExceededAt) {
+ public void setTimeLimitExceededAt(@ElapsedRealtimeLong long timeLimitExceededAt) {
mTimeLimitExceededAt = timeLimitExceededAt;
}
- @UptimeMillisLong
+ @ElapsedRealtimeLong
public long getTimeLimitExceededAt() {
return mTimeLimitExceededAt;
}
@@ -1858,8 +1858,8 @@
/**
* Called when a time-limited FGS starts.
*/
- public TimeLimitedFgsInfo createTimeLimitedFgsInfo(long nowUptime) {
- return new TimeLimitedFgsInfo(nowUptime);
+ public TimeLimitedFgsInfo createTimeLimitedFgsInfo(@ElapsedRealtimeLong long nowRealtime) {
+ return new TimeLimitedFgsInfo(nowRealtime);
}
/**
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index b8bfeda..e59de6a 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -2773,15 +2773,15 @@
}
code = AppOpsManager.opToSwitch(code);
UidState uidState = getUidStateLocked(uid, false);
- if (uidState != null
- && mAppOpsCheckingService.getUidMode(
- uidState.uid, getPersistentId(virtualDeviceId), code)
- != AppOpsManager.opToDefaultMode(code)) {
- final int rawMode =
- mAppOpsCheckingService.getUidMode(
- uidState.uid, getPersistentId(virtualDeviceId), code);
- return raw ? rawMode : uidState.evalMode(code, rawMode);
+ if (uidState != null) {
+ int rawUidMode = mAppOpsCheckingService.getUidMode(
+ uidState.uid, getPersistentId(virtualDeviceId), code);
+
+ if (rawUidMode != AppOpsManager.opToDefaultMode(code)) {
+ return raw ? rawUidMode : uidState.evalMode(code, rawUidMode);
+ }
}
+
Op op = getOpLocked(code, uid, packageName, null, false, pvr.bypass, /* edit */ false);
if (op == null) {
return AppOpsManager.opToDefaultMode(code);
@@ -3682,26 +3682,24 @@
isRestricted = isOpRestrictedLocked(uid, code, packageName, attributionTag,
virtualDeviceId, pvr.bypass, false);
final int switchCode = AppOpsManager.opToSwitch(code);
+
+ int rawUidMode;
if (isOpAllowedForUid(uid)) {
// Op is always allowed for the UID, do nothing.
// If there is a non-default per UID policy (we set UID op mode only if
// non-default) it takes over, otherwise use the per package policy.
- } else if (mAppOpsCheckingService.getUidMode(
- uidState.uid, getPersistentId(virtualDeviceId), switchCode)
+ } else if ((rawUidMode =
+ mAppOpsCheckingService.getUidMode(
+ uidState.uid, getPersistentId(virtualDeviceId), switchCode))
!= AppOpsManager.opToDefaultMode(switchCode)) {
- final int uidMode =
- uidState.evalMode(
- code,
- mAppOpsCheckingService.getUidMode(
- uidState.uid,
- getPersistentId(virtualDeviceId),
- switchCode));
+ final int uidMode = uidState.evalMode(code, rawUidMode);
if (!shouldStartForMode(uidMode, startIfModeDefault)) {
if (DEBUG) {
Slog.d(TAG, "startOperation: uid reject #" + uidMode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
- + packageName + " flags: " + AppOpsManager.flagsToString(flags));
+ + packageName + " flags: "
+ + AppOpsManager.flagsToString(flags));
}
attributedOp.rejected(uidState.getState(), flags);
scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
@@ -3710,8 +3708,8 @@
return new SyncNotedAppOp(uidMode, code, attributionTag, packageName);
}
} else {
- final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, uid, true)
- : op;
+ final Op switchOp =
+ switchCode != code ? getOpLocked(ops, switchCode, uid, true) : op;
final int mode =
switchOp.uidState.evalMode(
switchOp.op,
@@ -3721,9 +3719,12 @@
UserHandle.getUserId(switchOp.uid)));
if (mode != AppOpsManager.MODE_ALLOWED
&& (!startIfModeDefault || mode != MODE_DEFAULT)) {
- if (DEBUG) Slog.d(TAG, "startOperation: reject #" + mode + " for code "
- + switchCode + " (" + code + ") uid " + uid + " package "
- + packageName + " flags: " + AppOpsManager.flagsToString(flags));
+ if (DEBUG) {
+ Slog.d(TAG, "startOperation: reject #" + mode + " for code "
+ + switchCode + " (" + code + ") uid " + uid + " package "
+ + packageName + " flags: "
+ + AppOpsManager.flagsToString(flags));
+ }
attributedOp.rejected(uidState.getState(), flags);
scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
virtualDeviceId, flags, mode, startType, attributionFlags,
@@ -3731,6 +3732,7 @@
return new SyncNotedAppOp(mode, code, attributionTag, packageName);
}
}
+
if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
+ " package " + packageName + " restricted: " + isRestricted
+ " flags: " + AppOpsManager.flagsToString(flags));
diff --git a/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java b/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
index 3d20efc..f5a2f34 100644
--- a/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
+++ b/services/core/java/com/android/server/biometrics/sensors/SensorOverlays.java
@@ -16,12 +16,10 @@
package com.android.server.biometrics.sensors;
-import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.biometrics.BiometricRequestConstants;
-import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
import android.os.RemoteException;
@@ -45,22 +43,6 @@
@NonNull private final Optional<IUdfpsOverlayController> mUdfpsOverlayController;
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- @NonNull private final Optional<ISidefpsController> mSidefpsController;
-
- /**
- * Create an overlay controller for each modality.
- *
- * @param udfpsOverlayController under display fps or null if not present on device
- * @param sidefpsController side fps or null if not present on device
- */
- public SensorOverlays(
- @Nullable IUdfpsOverlayController udfpsOverlayController,
- @Nullable ISidefpsController sidefpsController) {
- mUdfpsOverlayController = Optional.ofNullable(udfpsOverlayController);
- mSidefpsController = Optional.ofNullable(sidefpsController);
- }
-
/**
* Create an overlay controller for each modality.
*
@@ -68,8 +50,6 @@
*/
public SensorOverlays(@Nullable IUdfpsOverlayController udfpsOverlayController) {
mUdfpsOverlayController = Optional.ofNullable(udfpsOverlayController);
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- mSidefpsController = Optional.empty();
}
/**
@@ -81,16 +61,6 @@
*/
public void show(int sensorId, @BiometricRequestConstants.RequestReason int reason,
@NonNull AcquisitionClient<?> client) {
- if (!sidefpsControllerRefactor()) {
- if (mSidefpsController.isPresent()) {
- try {
- mSidefpsController.get().show(sensorId, reason);
- } catch (RemoteException e) {
- Slog.e(TAG, "Remote exception when showing the side-fps overlay", e);
- }
- }
- }
-
if (mUdfpsOverlayController.isPresent()) {
final IUdfpsOverlayControllerCallback callback =
new IUdfpsOverlayControllerCallback.Stub() {
@@ -115,16 +85,6 @@
* @param sensorId sensor id
*/
public void hide(int sensorId) {
- if (!sidefpsControllerRefactor()) {
- if (mSidefpsController.isPresent()) {
- try {
- mSidefpsController.get().hide(sensorId);
- } catch (RemoteException e) {
- Slog.e(TAG, "Remote exception when hiding the side-fps overlay", e);
- }
- }
- }
-
if (mUdfpsOverlayController.isPresent()) {
try {
mUdfpsOverlayController.get().hideUdfpsOverlay(sensorId);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index deda93c7..4c86f57 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -57,7 +57,6 @@
import android.hardware.fingerprint.IFingerprintClientActiveCallback;
import android.hardware.fingerprint.IFingerprintService;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.Binder;
import android.os.Build;
@@ -974,17 +973,6 @@
}
}
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
- @Override
- public void setSidefpsController(@NonNull ISidefpsController controller) {
- super.setSidefpsController_enforcePermission();
-
- for (ServiceProvider provider : mRegistry.getProviders()) {
- provider.setSidefpsController(controller);
- }
- }
-
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
public void onPowerPressed() {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
index c2d1169..a6cf2f4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java
@@ -28,7 +28,6 @@
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.IBinder;
@@ -137,13 +136,6 @@
void onPowerPressed();
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- /**
- * Sets side-fps controller
- * @param controller side-fps controller
- */
- void setSidefpsController(@NonNull ISidefpsController controller);
-
@NonNull
ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback,
@NonNull String opPackageName);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index acc086b..f9f56ee 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -22,8 +22,6 @@
import static android.hardware.fingerprint.FingerprintManager.getAcquiredString;
import static android.hardware.fingerprint.FingerprintManager.getErrorString;
-import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.TaskStackListener;
@@ -35,6 +33,7 @@
import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.common.ICancellationSignal;
+import android.hardware.biometrics.common.OperationState;
import android.hardware.biometrics.events.AuthenticationAcquiredInfo;
import android.hardware.biometrics.events.AuthenticationErrorInfo;
import android.hardware.biometrics.events.AuthenticationFailedInfo;
@@ -46,7 +45,6 @@
import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.IBinder;
import android.os.RemoteException;
@@ -111,8 +109,6 @@
boolean isStrongBiometric,
@Nullable TaskStackListener taskStackListener,
@Nullable IUdfpsOverlayController udfpsOverlayController,
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- @Nullable ISidefpsController sidefpsController,
@NonNull AuthenticationStateListeners authenticationStateListeners,
boolean allowBackgroundAuthentication,
@NonNull FingerprintSensorPropertiesInternal sensorProps,
@@ -137,11 +133,7 @@
false /* shouldVibrate */,
biometricStrength);
setRequestId(requestId);
- if (sidefpsControllerRefactor()) {
- mSensorOverlays = new SensorOverlays(udfpsOverlayController);
- } else {
- mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
- }
+ mSensorOverlays = new SensorOverlays(udfpsOverlayController);
mAuthenticationStateListeners = authenticationStateListeners;
mIsStrongBiometric = isStrongBiometric;
mSensorProps = sensorProps;
@@ -198,11 +190,9 @@
getRequestReason(), mIsStrongBiometric, getTargetUserId()).build()
);
}
- if (sidefpsControllerRefactor()) {
- mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
- .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
- );
- }
+ mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+ .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
+ );
} else {
mState = STATE_STARTED_PAUSED_ATTEMPTED;
if (reportBiometricAuthAttempts()) {
@@ -287,23 +277,18 @@
resetIgnoreDisplayTouches();
mSensorOverlays.hide(getSensorId());
- if (sidefpsControllerRefactor()) {
- mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
- .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
- );
- }
+ mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+ .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
+ );
}
@Override
protected void startHalOperation() {
resetIgnoreDisplayTouches();
mSensorOverlays.show(getSensorId(), getRequestReason(), this);
- if (sidefpsControllerRefactor()) {
- mAuthenticationStateListeners.onAuthenticationStarted(new AuthenticationStartedInfo
- .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
- );
- }
-
+ mAuthenticationStateListeners.onAuthenticationStarted(new AuthenticationStartedInfo
+ .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
+ );
try {
doAuthenticate();
} catch (RemoteException e) {
@@ -344,6 +329,12 @@
if (session.hasContextMethods()) {
try {
session.getSession().onContextChanged(ctx);
+ // TODO(b/317414324): Deprecate setIgnoreDisplayTouches
+ if (ctx.operationState != null && ctx.operationState.getTag()
+ == OperationState.fingerprintOperationState) {
+ session.getSession().setIgnoreDisplayTouches(ctx.operationState
+ .getFingerprintOperationState().isHardwareIgnoringTouches);
+ }
} catch (RemoteException e) {
Slog.e(TAG, "Unable to notify context changed", e);
}
@@ -362,11 +353,9 @@
protected void stopHalOperation() {
resetIgnoreDisplayTouches();
mSensorOverlays.hide(getSensorId());
- if (sidefpsControllerRefactor()) {
- mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
- .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
- );
- }
+ mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+ .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
+ );
unsubscribeBiometricContext();
if (mCancellationSignal != null) {
@@ -468,11 +457,9 @@
resetIgnoreDisplayTouches();
mSensorOverlays.hide(getSensorId());
- if (sidefpsControllerRefactor()) {
- mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
- .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
- );
- }
+ mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+ .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
+ );
mCallback.onClientFinished(this, false /* success */);
}
@@ -505,11 +492,9 @@
resetIgnoreDisplayTouches();
mSensorOverlays.hide(getSensorId());
- if (sidefpsControllerRefactor()) {
- mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
- .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
- );
- }
+ mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+ .Builder(BiometricSourceType.FINGERPRINT, getRequestReason()).build()
+ );
mCallback.onClientFinished(this, false /* success */);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
index b6c33ba..36af5db 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
@@ -16,8 +16,6 @@
package com.android.server.biometrics.sensors.fingerprint.aidl;
-import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -77,12 +75,7 @@
setRequestId(requestId);
mAuthenticationStateListeners = authenticationStateListeners;
mIsStrongBiometric = isStrongBiometric;
- if (sidefpsControllerRefactor()) {
- mSensorOverlays = new SensorOverlays(udfpsOverlayController);
- } else {
- mSensorOverlays = new SensorOverlays(
- udfpsOverlayController, null /* sideFpsController */);
- }
+ mSensorOverlays = new SensorOverlays(udfpsOverlayController);
mOptions = options;
}
@@ -96,12 +89,10 @@
protected void stopHalOperation() {
resetIgnoreDisplayTouches();
mSensorOverlays.hide(getSensorId());
- if (sidefpsControllerRefactor()) {
- mAuthenticationStateListeners.onAuthenticationStopped(
- new AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT,
- BiometricRequestConstants.REASON_AUTH_KEYGUARD).build()
- );
- }
+ mAuthenticationStateListeners.onAuthenticationStopped(
+ new AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT,
+ BiometricRequestConstants.REASON_AUTH_KEYGUARD).build()
+ );
unsubscribeBiometricContext();
if (mCancellationSignal != null) {
@@ -119,25 +110,19 @@
resetIgnoreDisplayTouches();
mSensorOverlays.show(getSensorId(), BiometricRequestConstants.REASON_AUTH_KEYGUARD,
this);
-
- if (sidefpsControllerRefactor()) {
- mAuthenticationStateListeners.onAuthenticationStarted(
- new AuthenticationStartedInfo.Builder(BiometricSourceType.FINGERPRINT,
- BiometricRequestConstants.REASON_AUTH_KEYGUARD).build()
- );
- }
-
+ mAuthenticationStateListeners.onAuthenticationStarted(
+ new AuthenticationStartedInfo.Builder(BiometricSourceType.FINGERPRINT,
+ BiometricRequestConstants.REASON_AUTH_KEYGUARD).build()
+ );
try {
doDetectInteraction();
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception when requesting finger detect", e);
mSensorOverlays.hide(getSensorId());
- if (sidefpsControllerRefactor()) {
- mAuthenticationStateListeners.onAuthenticationStopped(
- new AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT,
- BiometricRequestConstants.REASON_AUTH_KEYGUARD).build()
- );
- }
+ mAuthenticationStateListeners.onAuthenticationStopped(
+ new AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT,
+ BiometricRequestConstants.REASON_AUTH_KEYGUARD).build()
+ );
mCallback.onClientFinished(this, false /* success */);
}
}
@@ -154,14 +139,12 @@
} catch (RemoteException e) {
Slog.e(TAG, "Unable to start detect interaction", e);
mSensorOverlays.hide(getSensorId());
- if (sidefpsControllerRefactor()) {
- mAuthenticationStateListeners.onAuthenticationStopped(
- new AuthenticationStoppedInfo.Builder(
- BiometricSourceType.FINGERPRINT,
- BiometricRequestConstants.REASON_AUTH_KEYGUARD
- ).build()
- );
- }
+ mAuthenticationStateListeners.onAuthenticationStopped(
+ new AuthenticationStoppedInfo.Builder(
+ BiometricSourceType.FINGERPRINT,
+ BiometricRequestConstants.REASON_AUTH_KEYGUARD
+ ).build()
+ );
mCallback.onClientFinished(this, false /* success */);
}
}, ctx -> {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index 3d170db..3a72d7e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -22,8 +22,6 @@
import static android.hardware.fingerprint.FingerprintManager.getAcquiredString;
import static android.hardware.fingerprint.FingerprintManager.getErrorString;
-import static com.android.systemui.shared.Flags.sidefpsControllerRefactor;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -43,7 +41,6 @@
import android.hardware.fingerprint.FingerprintEnrollOptions;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.hardware.keymaster.HardwareAuthToken;
import android.os.IBinder;
@@ -106,8 +103,6 @@
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull FingerprintSensorPropertiesInternal sensorProps,
@Nullable IUdfpsOverlayController udfpsOverlayController,
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- @Nullable ISidefpsController sidefpsController,
@NonNull AuthenticationStateListeners authenticationStateListeners,
int maxTemplatesPerUser, @FingerprintManager.EnrollReason int enrollReason,
@NonNull FingerprintEnrollOptions options) {
@@ -118,11 +113,7 @@
BiometricFingerprintConstants.reasonToMetric(options.getEnrollReason()));
setRequestId(requestId);
mSensorProps = sensorProps;
- if (sidefpsControllerRefactor()) {
- mSensorOverlays = new SensorOverlays(udfpsOverlayController);
- } else {
- mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
- }
+ mSensorOverlays = new SensorOverlays(udfpsOverlayController);
mAuthenticationStateListeners = authenticationStateListeners;
mMaxTemplatesPerUser = maxTemplatesPerUser;
@@ -161,13 +152,11 @@
if (remaining == 0) {
resetIgnoreDisplayTouches();
mSensorOverlays.hide(getSensorId());
- if (sidefpsControllerRefactor()) {
- mAuthenticationStateListeners.onAuthenticationStopped(
- new AuthenticationStoppedInfo.Builder(
- BiometricSourceType.FINGERPRINT,
- getRequestReasonFromFingerprintEnrollReason(mEnrollReason)).build()
- );
- }
+ mAuthenticationStateListeners.onAuthenticationStopped(
+ new AuthenticationStoppedInfo.Builder(
+ BiometricSourceType.FINGERPRINT,
+ getRequestReasonFromFingerprintEnrollReason(mEnrollReason)).build()
+ );
}
}
@@ -224,12 +213,10 @@
resetIgnoreDisplayTouches();
mSensorOverlays.hide(getSensorId());
- if (sidefpsControllerRefactor()) {
- mAuthenticationStateListeners.onAuthenticationStopped(
- new AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT,
- getRequestReasonFromFingerprintEnrollReason(mEnrollReason)).build()
- );
- }
+ mAuthenticationStateListeners.onAuthenticationStopped(
+ new AuthenticationStoppedInfo.Builder(BiometricSourceType.FINGERPRINT,
+ getRequestReasonFromFingerprintEnrollReason(mEnrollReason)).build()
+ );
}
@Override
@@ -243,12 +230,10 @@
resetIgnoreDisplayTouches();
mSensorOverlays.show(getSensorId(),
getRequestReasonFromFingerprintEnrollReason(mEnrollReason), this);
- if (sidefpsControllerRefactor()) {
- mAuthenticationStateListeners.onAuthenticationStarted(new AuthenticationStartedInfo
- .Builder(BiometricSourceType.FINGERPRINT,
- getRequestReasonFromFingerprintEnrollReason(mEnrollReason)).build()
- );
- }
+ mAuthenticationStateListeners.onAuthenticationStarted(new AuthenticationStartedInfo
+ .Builder(BiometricSourceType.FINGERPRINT,
+ getRequestReasonFromFingerprintEnrollReason(mEnrollReason)).build()
+ );
BiometricNotificationUtils.cancelBadCalibrationNotification(getContext());
try {
@@ -294,12 +279,10 @@
protected void stopHalOperation() {
resetIgnoreDisplayTouches();
mSensorOverlays.hide(getSensorId());
- if (sidefpsControllerRefactor()) {
- mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
- .Builder(BiometricSourceType.FINGERPRINT,
- getRequestReasonFromFingerprintEnrollReason(mEnrollReason)).build()
- );
- }
+ mAuthenticationStateListeners.onAuthenticationStopped(new AuthenticationStoppedInfo
+ .Builder(BiometricSourceType.FINGERPRINT,
+ getRequestReasonFromFingerprintEnrollReason(mEnrollReason)).build()
+ );
unsubscribeBiometricContext();
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index f485a65..6874c71 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -43,7 +43,6 @@
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.Binder;
import android.os.Build;
@@ -131,8 +130,6 @@
@NonNull private final BiometricHandlerProvider mBiometricHandlerProvider;
@Nullable private IFingerprint mDaemon;
@Nullable private IUdfpsOverlayController mUdfpsOverlayController;
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- @Nullable private ISidefpsController mSidefpsController;
private final AuthSessionCoordinator mAuthSessionCoordinator;
@Nullable private AuthenticationStatsCollector mAuthenticationStatsCollector;
@Nullable private IVirtualHal mVhal;
@@ -509,8 +506,8 @@
BiometricsProtoEnums.CLIENT_UNKNOWN, mAuthenticationStatsCollector),
mBiometricContext,
mFingerprintSensors.get(sensorId).getSensorProperties(),
- mUdfpsOverlayController, mSidefpsController,
- mAuthenticationStateListeners, maxTemplatesPerUser, enrollReason, options);
+ mUdfpsOverlayController, mAuthenticationStateListeners, maxTemplatesPerUser,
+ enrollReason, options);
scheduleForSensor(sensorId, client, mBiometricStateCallback);
});
return id;
@@ -565,8 +562,8 @@
mAuthenticationStatsCollector),
mBiometricContext, isStrongBiometric,
mTaskStackListener,
- mUdfpsOverlayController, mSidefpsController,
- mAuthenticationStateListeners, allowBackgroundAuthentication,
+ mUdfpsOverlayController, mAuthenticationStateListeners,
+ allowBackgroundAuthentication,
mFingerprintSensors.get(sensorId).getSensorProperties(),
Utils.getCurrentStrength(sensorId),
lockoutTracker);
@@ -801,12 +798,6 @@
}
}
- // TODO(b/288175061): remove with Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
- @Override
- public void setSidefpsController(@NonNull ISidefpsController controller) {
- mSidefpsController = controller;
- }
-
@Override
public void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto,
boolean clearSchedulerBuffer) {
diff --git a/services/core/java/com/android/server/display/BrightnessRangeController.java b/services/core/java/com/android/server/display/BrightnessRangeController.java
index dc0e80c..9b37418 100644
--- a/services/core/java/com/android/server/display/BrightnessRangeController.java
+++ b/services/core/java/com/android/server/display/BrightnessRangeController.java
@@ -19,7 +19,6 @@
import android.hardware.display.BrightnessInfo;
import android.os.Handler;
import android.os.IBinder;
-import android.os.PowerManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.brightness.clamper.HdrClamper;
@@ -148,9 +147,7 @@
float getHdrBrightnessValue() {
float hdrBrightness = mHbmController.getHdrBrightnessValue();
- float brightnessMax = mUseHdrClamper ? mHdrClamper.getMaxBrightness()
- : PowerManager.BRIGHTNESS_MAX;
- return Math.min(hdrBrightness, brightnessMax);
+ return mUseHdrClamper ? mHdrClamper.clamp(hdrBrightness) : hdrBrightness;
}
float getTransitionPoint() {
diff --git a/services/core/java/com/android/server/display/DisplayBrightnessState.java b/services/core/java/com/android/server/display/DisplayBrightnessState.java
index e3e3be2..baa154d 100644
--- a/services/core/java/com/android/server/display/DisplayBrightnessState.java
+++ b/services/core/java/com/android/server/display/DisplayBrightnessState.java
@@ -45,6 +45,7 @@
private final float mCustomAnimationRate;
private final BrightnessEvent mBrightnessEvent;
+ private final int mBrightnessAdjustmentFlag;
private DisplayBrightnessState(Builder builder) {
mBrightness = builder.getBrightness();
@@ -58,6 +59,7 @@
mCustomAnimationRate = builder.getCustomAnimationRate();
mShouldUpdateScreenBrightnessSetting = builder.shouldUpdateScreenBrightnessSetting();
mBrightnessEvent = builder.getBrightnessEvent();
+ mBrightnessAdjustmentFlag = builder.getBrightnessAdjustmentFlag();
}
/**
@@ -138,6 +140,14 @@
return mBrightnessEvent;
}
+ /**
+ * Gets the flag representing the reason for the brightness adjustment. This can be
+ * automatic(e.g. because of the change in the lux), or user initiated(e.g. moving the slider)
+ */
+ public int getBrightnessAdjustmentFlag() {
+ return mBrightnessAdjustmentFlag;
+ }
+
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder("DisplayBrightnessState:");
@@ -157,6 +167,7 @@
.append(mShouldUpdateScreenBrightnessSetting);
stringBuilder.append("\n mBrightnessEvent:")
.append(Objects.toString(mBrightnessEvent, "null"));
+ stringBuilder.append("\n mBrightnessAdjustmentFlag:").append(mBrightnessAdjustmentFlag);
return stringBuilder.toString();
}
@@ -187,7 +198,8 @@
&& mCustomAnimationRate == otherState.getCustomAnimationRate()
&& mShouldUpdateScreenBrightnessSetting
== otherState.shouldUpdateScreenBrightnessSetting()
- && Objects.equals(mBrightnessEvent, otherState.getBrightnessEvent());
+ && Objects.equals(mBrightnessEvent, otherState.getBrightnessEvent())
+ && mBrightnessAdjustmentFlag == otherState.getBrightnessAdjustmentFlag();
}
@Override
@@ -195,7 +207,7 @@
return Objects.hash(mBrightness, mSdrBrightness, mBrightnessReason,
mShouldUseAutoBrightness, mIsSlowChange, mMaxBrightness, mMinBrightness,
mCustomAnimationRate,
- mShouldUpdateScreenBrightnessSetting, mBrightnessEvent);
+ mShouldUpdateScreenBrightnessSetting, mBrightnessEvent, mBrightnessAdjustmentFlag);
}
/**
@@ -222,6 +234,8 @@
private BrightnessEvent mBrightnessEvent;
+ public int mBrightnessAdjustmentFlag = 0;
+
/**
* Create a builder starting with the values from the specified {@link
* DisplayBrightnessState}.
@@ -242,6 +256,7 @@
builder.setShouldUpdateScreenBrightnessSetting(
state.shouldUpdateScreenBrightnessSetting());
builder.setBrightnessEvent(state.getBrightnessEvent());
+ builder.setBrightnessAdjustmentFlag(state.getBrightnessAdjustmentFlag());
return builder;
}
@@ -418,7 +433,6 @@
return new DisplayBrightnessState(this);
}
-
/**
* This is used to get the BrightnessEvent object from its builder
*/
@@ -434,5 +448,21 @@
mBrightnessEvent = brightnessEvent;
return this;
}
+
+ /**
+ * This is used to get the brightness adjustment flag from its builder
+ */
+ public int getBrightnessAdjustmentFlag() {
+ return mBrightnessAdjustmentFlag;
+ }
+
+
+ /**
+ * This is used to set the brightness adjustment flag
+ */
+ public Builder setBrightnessAdjustmentFlag(int brightnessAdjustmentFlag) {
+ mBrightnessAdjustmentFlag = brightnessAdjustmentFlag;
+ return this;
+ }
}
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index e88ace1..c5d8686 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1345,6 +1345,7 @@
boolean slowChange = displayBrightnessState.isSlowChange();
// custom transition duration
float customAnimationRate = displayBrightnessState.getCustomAnimationRate();
+ int brightnessAdjustmentFlags = displayBrightnessState.getBrightnessAdjustmentFlag();
final boolean userSetBrightnessChanged =
mDisplayBrightnessController.getIsUserSetScreenBrightnessUpdated();
if (displayBrightnessState.getBrightnessEvent() != null) {
@@ -1392,15 +1393,10 @@
displayBrightnessState.shouldUpdateScreenBrightnessSetting();
float currentBrightnessSetting = mDisplayBrightnessController.getCurrentBrightness();
// Apply auto-brightness.
- int brightnessAdjustmentFlags = 0;
// All the conditions inside this if block will be moved to AutomaticBrightnessStrategy
if (mFlags.isRefactorDisplayPowerControllerEnabled()
&& displayBrightnessState.getBrightnessReason().getReason()
== BrightnessReason.REASON_AUTOMATIC) {
- brightnessAdjustmentFlags =
- mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentReasonsFlags();
- updateScreenBrightnessSetting = currentBrightnessSetting != brightnessState;
- mBrightnessReasonTemp.setReason(BrightnessReason.REASON_AUTOMATIC);
if (mScreenOffBrightnessSensorController != null) {
mScreenOffBrightnessSensorController.setLightSensorEnabled(false);
}
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
index 8b3e4a4..6a88a76 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
@@ -146,7 +146,8 @@
synchronized (mLock) {
mDisplayBrightnessStrategy = mDisplayBrightnessStrategySelector.selectStrategy(
constructStrategySelectionRequest(displayPowerRequest, targetDisplayState));
- state = mDisplayBrightnessStrategy.updateBrightness(displayPowerRequest);
+ state = mDisplayBrightnessStrategy
+ .updateBrightness(constructStrategyExecutionRequest(displayPowerRequest));
}
// This is a temporary measure until AutomaticBrightnessStrategy works as a traditional
@@ -550,4 +551,10 @@
return new StrategySelectionRequest(displayPowerRequest, targetDisplayState,
lastUserSetScreenBrightness, userSetBrightnessChanged);
}
+
+ private StrategyExecutionRequest constructStrategyExecutionRequest(
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+ float currentScreenBrightness = getCurrentBrightness();
+ return new StrategyExecutionRequest(displayPowerRequest, currentScreenBrightness);
+ }
}
diff --git a/services/core/java/com/android/server/display/brightness/StrategyExecutionRequest.java b/services/core/java/com/android/server/display/brightness/StrategyExecutionRequest.java
new file mode 100644
index 0000000..82c0bbf
--- /dev/null
+++ b/services/core/java/com/android/server/display/brightness/StrategyExecutionRequest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2024 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.display.brightness;
+
+import android.hardware.display.DisplayManagerInternal;
+
+import java.util.Objects;
+
+/**
+ * A wrapper class to encapsulate the request to execute the selected strategy
+ */
+public final class StrategyExecutionRequest {
+ // The request to change the associated display's state and brightness
+ private final DisplayManagerInternal.DisplayPowerRequest mDisplayPowerRequest;
+
+ private final float mCurrentScreenBrightness;
+
+ public StrategyExecutionRequest(DisplayManagerInternal.DisplayPowerRequest displayPowerRequest,
+ float currentScreenBrightness) {
+ mDisplayPowerRequest = displayPowerRequest;
+ mCurrentScreenBrightness = currentScreenBrightness;
+ }
+
+ public DisplayManagerInternal.DisplayPowerRequest getDisplayPowerRequest() {
+ return mDisplayPowerRequest;
+ }
+
+ public float getCurrentScreenBrightness() {
+ return mCurrentScreenBrightness;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof StrategyExecutionRequest)) {
+ return false;
+ }
+ StrategyExecutionRequest other = (StrategyExecutionRequest) obj;
+ return Objects.equals(mDisplayPowerRequest, other.getDisplayPowerRequest())
+ && mCurrentScreenBrightness == other.getCurrentScreenBrightness();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mDisplayPowerRequest, mCurrentScreenBrightness);
+ }
+}
diff --git a/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java b/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java
index f1cb66c..902daa4 100644
--- a/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java
+++ b/services/core/java/com/android/server/display/brightness/clamper/HdrClamper.java
@@ -59,6 +59,11 @@
private boolean mAutoBrightnessEnabled = false;
+ /**
+ * Indicates that maxBrightness is changed, and we should use slow transition
+ */
+ private boolean mUseSlowTransition = false;
+
public HdrClamper(BrightnessClamperController.ClamperChangeListener clamperChangeListener,
Handler handler) {
this(clamperChangeListener, handler, new Injector());
@@ -72,6 +77,7 @@
mDebouncer = () -> {
mTransitionRate = mDesiredTransitionRate;
mMaxBrightness = mDesiredMaxBrightness;
+ mUseSlowTransition = true;
mClamperChangeListener.onChanged();
};
mHdrListener = injector.getHdrListener((visible) -> {
@@ -80,14 +86,24 @@
}, handler);
}
- // Called in same looper: mHandler.getLooper()
+ /**
+ * Applies clamping
+ * Called in same looper: mHandler.getLooper()
+ */
+ public float clamp(float brightness) {
+ return Math.min(brightness, mMaxBrightness);
+ }
+
+ @VisibleForTesting
public float getMaxBrightness() {
return mMaxBrightness;
}
// Called in same looper: mHandler.getLooper()
public float getTransitionRate() {
- return mTransitionRate;
+ float expectedTransitionRate = mUseSlowTransition ? mTransitionRate : -1;
+ mUseSlowTransition = false;
+ return expectedTransitionRate;
}
/**
@@ -173,7 +189,8 @@
mMaxBrightness = PowerManager.BRIGHTNESS_MAX;
mDesiredMaxBrightness = PowerManager.BRIGHTNESS_MAX;
mDesiredTransitionRate = -1f;
- mTransitionRate = 1f;
+ mTransitionRate = -1f;
+ mUseSlowTransition = false;
mClamperChangeListener.onChanged();
}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java
index 4be7332..5c4fa842 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategy.java
@@ -20,7 +20,6 @@
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.display.BrightnessConfiguration;
-import android.hardware.display.DisplayManagerInternal;
import android.os.PowerManager;
import android.os.UserHandle;
import android.provider.Settings;
@@ -32,6 +31,7 @@
import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -96,13 +96,21 @@
// want to re-evaluate the auto-brightness state
private boolean mIsConfigured;
- public AutomaticBrightnessStrategy(Context context, int displayId) {
+ private Injector mInjector;
+
+ @VisibleForTesting
+ AutomaticBrightnessStrategy(Context context, int displayId, Injector injector) {
super(context, displayId);
mContext = context;
mDisplayId = displayId;
mAutoBrightnessAdjustment = getAutoBrightnessAdjustmentSetting();
mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+ mInjector = (injector == null) ? new RealInjector() : injector;
+ }
+
+ public AutomaticBrightnessStrategy(Context context, int displayId) {
+ this(context, displayId, null);
}
/**
@@ -252,10 +260,10 @@
@Override
public DisplayBrightnessState updateBrightness(
- DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+ StrategyExecutionRequest strategyExecutionRequest) {
BrightnessReason brightnessReason = new BrightnessReason();
brightnessReason.setReason(BrightnessReason.REASON_AUTOMATIC);
- BrightnessEvent brightnessEvent = new BrightnessEvent(mDisplayId);
+ BrightnessEvent brightnessEvent = mInjector.getBrightnessEvent(mDisplayId);
float brightness = getAutomaticScreenBrightness(brightnessEvent);
return new DisplayBrightnessState.Builder()
.setBrightness(brightness)
@@ -265,6 +273,9 @@
.setIsSlowChange(hasAppliedAutoBrightness()
&& !getAutoBrightnessAdjustmentChanged())
.setBrightnessEvent(brightnessEvent)
+ .setBrightnessAdjustmentFlag(mAutoBrightnessAdjustmentReasonsFlags)
+ .setShouldUpdateScreenBrightnessSetting(
+ brightness != strategyExecutionRequest.getCurrentScreenBrightness())
.build();
}
@@ -360,13 +371,6 @@
}
/**
- * Gets the auto-brightness adjustment flag change reason
- */
- public int getAutoBrightnessAdjustmentReasonsFlags() {
- return mAutoBrightnessAdjustmentReasonsFlags;
- }
-
- /**
* Returns if the auto brightness has been applied
*/
public boolean hasAppliedAutoBrightness() {
@@ -497,4 +501,15 @@
Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, 0.0f, UserHandle.USER_CURRENT);
return Float.isNaN(adj) ? 0.0f : BrightnessUtils.clampBrightnessAdjustment(adj);
}
+
+ @VisibleForTesting
+ interface Injector {
+ BrightnessEvent getBrightnessEvent(int displayId);
+ }
+
+ static class RealInjector implements Injector {
+ public BrightnessEvent getBrightnessEvent(int displayId) {
+ return new BrightnessEvent(displayId);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java
index 9c1acea..009a47a 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/BoostBrightnessStrategy.java
@@ -16,12 +16,12 @@
package com.android.server.display.brightness.strategy;
-import android.hardware.display.DisplayManagerInternal;
import android.os.PowerManager;
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -37,7 +37,7 @@
// Set the brightness to the maximum value when display brightness boost is requested
@Override
public DisplayBrightnessState updateBrightness(
- DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+ StrategyExecutionRequest strategyExecutionRequest) {
// Todo(b/241308599): Introduce a validator class and add validations before setting
// the brightness
DisplayBrightnessState displayBrightnessState =
diff --git a/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategy.java
index 61dd6d5..e96b83a 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/DisplayBrightnessStrategy.java
@@ -17,9 +17,9 @@
package com.android.server.display.brightness.strategy;
import android.annotation.NonNull;
-import android.hardware.display.DisplayManagerInternal;
import com.android.server.display.DisplayBrightnessState;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -33,10 +33,10 @@
/**
* Decides the DisplayBrightnessState that the system should change to.
*
- * @param displayPowerRequest The request to evaluate the updated brightness
+ * @param strategyExecutionRequest The request to evaluate the updated brightness
*/
DisplayBrightnessState updateBrightness(
- DisplayManagerInternal.DisplayPowerRequest displayPowerRequest);
+ StrategyExecutionRequest strategyExecutionRequest);
/**
* Returns the name of the Strategy
diff --git a/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
index 1f7efd1..2b493f3 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/DozeBrightnessStrategy.java
@@ -16,11 +16,10 @@
package com.android.server.display.brightness.strategy;
-import android.hardware.display.DisplayManagerInternal;
-
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -32,11 +31,12 @@
@Override
public DisplayBrightnessState updateBrightness(
- DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+ StrategyExecutionRequest strategyExecutionRequest) {
// Todo(b/241308599): Introduce a validator class and add validations before setting
// the brightness
return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_DOZE,
- displayPowerRequest.dozeScreenBrightness, displayPowerRequest.dozeScreenBrightness,
+ strategyExecutionRequest.getDisplayPowerRequest().dozeScreenBrightness,
+ strategyExecutionRequest.getDisplayPowerRequest().dozeScreenBrightness,
getName());
}
diff --git a/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java
index baac276..5a07ce2 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/FollowerBrightnessStrategy.java
@@ -16,12 +16,12 @@
package com.android.server.display.brightness.strategy;
-import android.hardware.display.DisplayManagerInternal;
import android.os.PowerManager;
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -49,7 +49,7 @@
@Override
public DisplayBrightnessState updateBrightness(
- DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+ StrategyExecutionRequest strategyExecutionRequest) {
// Todo(b/241308599): Introduce a validator class and add validations before setting
// the brightness
return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_FOLLOWER,
diff --git a/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
index dfd47a3..9dc6cff 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/InvalidBrightnessStrategy.java
@@ -16,12 +16,12 @@
package com.android.server.display.brightness.strategy;
-import android.hardware.display.DisplayManagerInternal;
import android.os.PowerManager;
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -32,7 +32,7 @@
public class InvalidBrightnessStrategy implements DisplayBrightnessStrategy {
@Override
public DisplayBrightnessState updateBrightness(
- DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+ StrategyExecutionRequest strategyExecutionRequest) {
return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_UNKNOWN,
PowerManager.BRIGHTNESS_INVALID_FLOAT, PowerManager.BRIGHTNESS_INVALID_FLOAT,
getName());
diff --git a/services/core/java/com/android/server/display/brightness/strategy/OffloadBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/OffloadBrightnessStrategy.java
index 60e5eb0..b46873a 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/OffloadBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/OffloadBrightnessStrategy.java
@@ -16,11 +16,11 @@
package com.android.server.display.brightness.strategy;
-import android.hardware.display.DisplayManagerInternal;
import android.os.PowerManager;
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import com.android.server.display.feature.DisplayManagerFlags;
@@ -42,7 +42,7 @@
@Override
public DisplayBrightnessState updateBrightness(
- DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+ StrategyExecutionRequest strategyExecutionRequest) {
float offloadBrightness = mOffloadScreenBrightness;
if (mDisplayManagerFlags.isRefactorDisplayPowerControllerEnabled()) {
// We reset the offload brightness to invalid so that there is no stale value lingering
diff --git a/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java
index 9605a88..a2982b1 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/OverrideBrightnessStrategy.java
@@ -16,11 +16,10 @@
package com.android.server.display.brightness.strategy;
-import android.hardware.display.DisplayManagerInternal;
-
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -31,12 +30,13 @@
public class OverrideBrightnessStrategy implements DisplayBrightnessStrategy {
@Override
public DisplayBrightnessState updateBrightness(
- DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+ StrategyExecutionRequest strategyExecutionRequest) {
// Todo(b/241308599): Introduce a validator class and add validations before setting
// the brightness
return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_OVERRIDE,
- displayPowerRequest.screenBrightnessOverride,
- displayPowerRequest.screenBrightnessOverride, getName());
+ strategyExecutionRequest.getDisplayPowerRequest().screenBrightnessOverride,
+ strategyExecutionRequest.getDisplayPowerRequest()
+ .screenBrightnessOverride, getName());
}
@Override
diff --git a/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
index c9dc298..6a3162c 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategy.java
@@ -16,12 +16,12 @@
package com.android.server.display.brightness.strategy;
-import android.hardware.display.DisplayManagerInternal;
import android.os.PowerManager;
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -32,7 +32,7 @@
public class ScreenOffBrightnessStrategy implements DisplayBrightnessStrategy {
@Override
public DisplayBrightnessState updateBrightness(
- DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+ StrategyExecutionRequest strategyExecutionRequest) {
// Todo(b/241308599): Introduce a validator class and add validations before setting
// the brightness
return BrightnessUtils.constructDisplayBrightnessState(BrightnessReason.REASON_SCREEN_OFF,
diff --git a/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java b/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java
index 6a691d1..6b8817a 100644
--- a/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java
+++ b/services/core/java/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategy.java
@@ -16,12 +16,12 @@
package com.android.server.display.brightness.strategy;
-import android.hardware.display.DisplayManagerInternal;
import android.os.PowerManager;
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import java.io.PrintWriter;
@@ -43,7 +43,7 @@
// WindowManager or based on the display state.
@Override
public DisplayBrightnessState updateBrightness(
- DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
+ StrategyExecutionRequest strategyExecutionRequest) {
// Todo(b/241308599): Introduce a validator class and add validations before setting
// the brightness
DisplayBrightnessState displayBrightnessState =
diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java
index 0e8a5fb..a818eab 100644
--- a/services/core/java/com/android/server/dreams/DreamController.java
+++ b/services/core/java/com/android/server/dreams/DreamController.java
@@ -249,6 +249,16 @@
mCurrentDream.mAppTask = appTask;
}
+ void setDreamHasFocus(boolean hasFocus) {
+ if (mCurrentDream != null) {
+ mCurrentDream.mDreamHasFocus = hasFocus;
+ }
+ }
+
+ boolean dreamHasFocus() {
+ return mCurrentDream != null && mCurrentDream.mDreamHasFocus;
+ }
+
/**
* Sends a user activity signal to PowerManager to stop the screen from turning off immediately
* if there hasn't been any user interaction in a while.
@@ -271,6 +281,21 @@
stopDreamInstance(immediate, reason, mCurrentDream);
}
+ public boolean bringDreamToFront() {
+ if (mCurrentDream == null || mCurrentDream.mService == null) {
+ return false;
+ }
+
+ try {
+ mCurrentDream.mService.comeToFront();
+ return true;
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error asking dream to come to the front", e);
+ }
+
+ return false;
+ }
+
/**
* Stops the given dream instance.
*
@@ -426,6 +451,7 @@
private String mStopReason;
private long mDreamStartTime;
public boolean mWakingGently;
+ public boolean mDreamHasFocus;
private final Runnable mStopPreviousDreamsIfNeeded = this::stopPreviousDreamsIfNeeded;
private final Runnable mReleaseWakeLockIfNeeded = this::releaseWakeLockIfNeeded;
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 42c9e08..fc63494 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -20,6 +20,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.service.dreams.Flags.dreamTracksFocus;
import static com.android.server.wm.ActivityInterceptorCallback.DREAM_MANAGER_ORDERED_ID;
@@ -406,8 +407,10 @@
/** Whether dreaming can start given user settings and the current dock/charge state. */
private boolean canStartDreamingInternal(boolean isScreenOn) {
synchronized (mLock) {
- // Can't start dreaming if we are already dreaming.
- if (isScreenOn && isDreamingInternal()) {
+ // Can't start dreaming if we are already dreaming and the dream has focus. If we are
+ // dreaming but the dream does not have focus, then the dream can be brought to the
+ // front so it does have focus.
+ if (isScreenOn && isDreamingInternal() && dreamHasFocus()) {
return false;
}
@@ -442,11 +445,20 @@
}
}
+ private boolean dreamHasFocus() {
+ // Dreams always had focus before they were able to track it.
+ return !dreamTracksFocus() || mController.dreamHasFocus();
+ }
+
protected void requestStartDreamFromShell() {
requestDreamInternal();
}
private void requestDreamInternal() {
+ if (isDreamingInternal() && !dreamHasFocus() && mController.bringDreamToFront()) {
+ return;
+ }
+
// Ask the power manager to nap. It will eventually call back into
// startDream() if/when it is appropriate to start dreaming.
// Because napping could cause the screen to turn off immediately if the dream
@@ -1128,6 +1140,16 @@
});
}
+ @Override
+ public void onDreamFocusChanged(boolean hasFocus) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ mController.setDreamHasFocus(hasFocus);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
boolean canLaunchDreamActivity(String dreamPackageName, String packageName,
int callingUid) {
if (dreamPackageName == null || packageName == null) {
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java b/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java
index b18871c..a0dbfa0 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubTransactionManager.java
@@ -28,6 +28,7 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Random;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -77,9 +78,12 @@
private final AtomicInteger mNextAvailableId = new AtomicInteger();
/**
- * The next available message sequence number
+ * The next available message sequence number. We choose a random
+ * number to start with to avoid collisions and limit the bound to
+ * half of the max value to avoid overflow.
*/
- private final AtomicInteger mNextAvailableMessageSequenceNumber = new AtomicInteger();
+ private final AtomicInteger mNextAvailableMessageSequenceNumber =
+ new AtomicInteger(new Random().nextInt(Integer.MAX_VALUE / 2));
/*
* An executor and the future object for scheduling timeout timers
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
index db83d4b..a7fd750 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
@@ -233,7 +233,7 @@
return false;
}
boolean bindDueToManagerScan =
- mIsManagerScanning && Flags.enablePreventionOfManagerScansWhenNoAppsScan();
+ mIsManagerScanning && !Flags.enablePreventionOfManagerScansWhenNoAppsScan();
if (!getSessionInfos().isEmpty() || bindDueToManagerScan) {
// We bind if any manager is scanning (regardless of whether an app is scanning) to give
// the opportunity for providers to publish routing sessions that were established
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index e50189b..869b89a 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -3411,7 +3411,14 @@
for (RouterRecord activeRouterRecord : activeRouterRecords) {
RouteDiscoveryPreference preference = activeRouterRecord.mDiscoveryPreference;
preferredFeatures.addAll(preference.getPreferredFeatures());
- if (activeRouterRecord.isActivelyScanning()) {
+
+ boolean isRouterRecordActivelyScanning =
+ Flags.enablePreventionOfManagerScansWhenNoAppsScan()
+ ? (activeRouterRecord.isActivelyScanning() || shouldForceActiveScan)
+ && !preference.getPreferredFeatures().isEmpty()
+ : activeRouterRecord.isActivelyScanning();
+
+ if (isRouterRecordActivelyScanning) {
activeScan = true;
activelyScanningPackages.add(activeRouterRecord.mPackageName);
}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 3d68555..a3c5d2d 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -66,7 +66,6 @@
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
-import android.os.DeadObjectException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -90,7 +89,6 @@
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
@@ -191,6 +189,9 @@
private final ForegroundServiceDelegationOptions mForegroundServiceDelegationOptions;
private final Object mLock = new Object();
+ // This field is partially guarded by mLock. Writes and non-atomic iterations (for example:
+ // index-based-iterations) must be guarded by mLock. But it is safe to acquire an iterator
+ // without acquiring mLock.
private final CopyOnWriteArrayList<ISessionControllerCallbackHolder>
mControllerCallbackHolders = new CopyOnWriteArrayList<>();
@@ -886,24 +887,9 @@
}
playbackState = mPlaybackState;
}
- Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
- for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
- try {
- holder.mCallback.onPlaybackStateChanged(playbackState);
- } catch (DeadObjectException e) {
- if (deadCallbackHolders == null) {
- deadCallbackHolders = new ArrayList<>();
- }
- deadCallbackHolders.add(holder);
- logCallbackException("Removing dead callback in pushPlaybackStateUpdate", holder,
- e);
- } catch (RemoteException e) {
- logCallbackException("unexpected exception in pushPlaybackStateUpdate", holder, e);
- }
- }
- if (deadCallbackHolders != null) {
- removeControllerHoldersSafely(deadCallbackHolders);
- }
+ performOnCallbackHolders(
+ "pushPlaybackStateUpdate",
+ holder -> holder.mCallback.onPlaybackStateChanged(playbackState));
}
private void pushMetadataUpdate() {
@@ -914,23 +900,8 @@
}
metadata = mMetadata;
}
- Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
- for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
- try {
- holder.mCallback.onMetadataChanged(metadata);
- } catch (DeadObjectException e) {
- if (deadCallbackHolders == null) {
- deadCallbackHolders = new ArrayList<>();
- }
- deadCallbackHolders.add(holder);
- logCallbackException("Removing dead callback in pushMetadataUpdate", holder, e);
- } catch (RemoteException e) {
- logCallbackException("unexpected exception in pushMetadataUpdate", holder, e);
- }
- }
- if (deadCallbackHolders != null) {
- removeControllerHoldersSafely(deadCallbackHolders);
- }
+ performOnCallbackHolders(
+ "pushMetadataUpdate", holder -> holder.mCallback.onMetadataChanged(metadata));
}
private void pushQueueUpdate() {
@@ -941,31 +912,18 @@
}
toSend = mQueue == null ? null : new ArrayList<>(mQueue);
}
- Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
- for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
- ParceledListSlice<QueueItem> parcelableQueue = null;
- if (toSend != null) {
- parcelableQueue = new ParceledListSlice<>(toSend);
- // Limit the size of initial Parcel to prevent binder buffer overflow
- // as onQueueChanged is an async binder call.
- parcelableQueue.setInlineCountLimit(1);
- }
-
- try {
- holder.mCallback.onQueueChanged(parcelableQueue);
- } catch (DeadObjectException e) {
- if (deadCallbackHolders == null) {
- deadCallbackHolders = new ArrayList<>();
- }
- deadCallbackHolders.add(holder);
- logCallbackException("Removing dead callback in pushQueueUpdate", holder, e);
- } catch (RemoteException e) {
- logCallbackException("unexpected exception in pushQueueUpdate", holder, e);
- }
- }
- if (deadCallbackHolders != null) {
- removeControllerHoldersSafely(deadCallbackHolders);
- }
+ performOnCallbackHolders(
+ "pushQueueUpdate",
+ holder -> {
+ ParceledListSlice<QueueItem> parcelableQueue = null;
+ if (toSend != null) {
+ parcelableQueue = new ParceledListSlice<>(toSend);
+ // Limit the size of initial Parcel to prevent binder buffer overflow
+ // as onQueueChanged is an async binder call.
+ parcelableQueue.setInlineCountLimit(1);
+ }
+ holder.mCallback.onQueueChanged(parcelableQueue);
+ });
}
private void pushQueueTitleUpdate() {
@@ -976,23 +934,8 @@
}
queueTitle = mQueueTitle;
}
- Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
- for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
- try {
- holder.mCallback.onQueueTitleChanged(queueTitle);
- } catch (DeadObjectException e) {
- if (deadCallbackHolders == null) {
- deadCallbackHolders = new ArrayList<>();
- }
- deadCallbackHolders.add(holder);
- logCallbackException("Removing dead callback in pushQueueTitleUpdate", holder, e);
- } catch (RemoteException e) {
- logCallbackException("unexpected exception in pushQueueTitleUpdate", holder, e);
- }
- }
- if (deadCallbackHolders != null) {
- removeControllerHoldersSafely(deadCallbackHolders);
- }
+ performOnCallbackHolders(
+ "pushQueueTitleUpdate", holder -> holder.mCallback.onQueueTitleChanged(queueTitle));
}
private void pushExtrasUpdate() {
@@ -1003,23 +946,8 @@
}
extras = mExtras;
}
- Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
- for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
- try {
- holder.mCallback.onExtrasChanged(extras);
- } catch (DeadObjectException e) {
- if (deadCallbackHolders == null) {
- deadCallbackHolders = new ArrayList<>();
- }
- deadCallbackHolders.add(holder);
- logCallbackException("Removing dead callback in pushExtrasUpdate", holder, e);
- } catch (RemoteException e) {
- logCallbackException("unexpected exception in pushExtrasUpdate", holder, e);
- }
- }
- if (deadCallbackHolders != null) {
- removeControllerHoldersSafely(deadCallbackHolders);
- }
+ performOnCallbackHolders(
+ "pushExtrasUpdate", holder -> holder.mCallback.onExtrasChanged(extras));
}
private void pushVolumeUpdate() {
@@ -1030,23 +958,8 @@
}
info = getVolumeAttributes();
}
- Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
- for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
- try {
- holder.mCallback.onVolumeInfoChanged(info);
- } catch (DeadObjectException e) {
- if (deadCallbackHolders == null) {
- deadCallbackHolders = new ArrayList<>();
- }
- deadCallbackHolders.add(holder);
- logCallbackException("Removing dead callback in pushVolumeUpdate", holder, e);
- } catch (RemoteException e) {
- logCallbackException("unexpected exception in pushVolumeUpdate", holder, e);
- }
- }
- if (deadCallbackHolders != null) {
- removeControllerHoldersSafely(deadCallbackHolders);
- }
+ performOnCallbackHolders(
+ "pushVolumeUpdate", holder -> holder.mCallback.onVolumeInfoChanged(info));
}
private void pushEvent(String event, Bundle data) {
@@ -1055,23 +968,7 @@
return;
}
}
- Collection<ISessionControllerCallbackHolder> deadCallbackHolders = null;
- for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
- try {
- holder.mCallback.onEvent(event, data);
- } catch (DeadObjectException e) {
- if (deadCallbackHolders == null) {
- deadCallbackHolders = new ArrayList<>();
- }
- deadCallbackHolders.add(holder);
- logCallbackException("Removing dead callback in pushEvent", holder, e);
- } catch (RemoteException e) {
- logCallbackException("unexpected exception in pushEvent", holder, e);
- }
- }
- if (deadCallbackHolders != null) {
- removeControllerHoldersSafely(deadCallbackHolders);
- }
+ performOnCallbackHolders("pushEvent", holder -> holder.mCallback.onEvent(event, data));
}
private void pushSessionDestroyed() {
@@ -1082,20 +979,37 @@
return;
}
}
+ performOnCallbackHolders(
+ "pushSessionDestroyed",
+ holder -> {
+ holder.mCallback.asBinder().unlinkToDeath(holder.mDeathMonitor, 0);
+ holder.mCallback.onSessionDestroyed();
+ });
+ // After notifying clear all listeners
+ synchronized (mLock) {
+ mControllerCallbackHolders.clear();
+ }
+ }
+
+ private interface ControllerCallbackCall {
+
+ void performOn(ISessionControllerCallbackHolder holder) throws RemoteException;
+ }
+
+ private void performOnCallbackHolders(String operationName, ControllerCallbackCall call) {
+ ArrayList<ISessionControllerCallbackHolder> deadCallbackHolders = new ArrayList<>();
for (ISessionControllerCallbackHolder holder : mControllerCallbackHolders) {
try {
- holder.mCallback.asBinder().unlinkToDeath(holder.mDeathMonitor, 0);
- holder.mCallback.onSessionDestroyed();
- } catch (NoSuchElementException e) {
- logCallbackException("error unlinking to binder death", holder, e);
- } catch (DeadObjectException e) {
- logCallbackException("Removing dead callback in pushSessionDestroyed", holder, e);
- } catch (RemoteException e) {
- logCallbackException("unexpected exception in pushSessionDestroyed", holder, e);
+ call.performOn(holder);
+ } catch (RemoteException | NoSuchElementException exception) {
+ deadCallbackHolders.add(holder);
+ logCallbackException(
+ "Exception while executing: " + operationName, holder, exception);
}
}
- // After notifying clear all listeners
- removeControllerHoldersSafely(null);
+ synchronized (mLock) {
+ mControllerCallbackHolders.removeAll(deadCallbackHolders);
+ }
}
private PlaybackState getStateWithUpdatedPosition() {
@@ -1143,17 +1057,6 @@
return -1;
}
- private void removeControllerHoldersSafely(
- Collection<ISessionControllerCallbackHolder> holders) {
- synchronized (mLock) {
- if (holders == null) {
- mControllerCallbackHolders.clear();
- } else {
- mControllerCallbackHolders.removeAll(holders);
- }
- }
- }
-
private PlaybackInfo getVolumeAttributes() {
int volumeType;
AudioAttributes attributes;
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index e75d0a3..38c95f7 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -502,8 +502,8 @@
pw.println(prefix + "uid=" + getSbn().getUid() + " userId=" + getSbn().getUserId());
pw.println(prefix + "opPkg=" + getSbn().getOpPkg());
pw.println(prefix + "icon=" + notification.getSmallIcon());
- pw.println(prefix + "flags=0x" + Integer.toHexString(notification.flags));
- pw.println(prefix + "originalFlags=0x" + Integer.toHexString(mOriginalFlags));
+ pw.println(prefix + "flags=" + Notification.flagsToString(notification.flags));
+ pw.println(prefix + "originalFlags=" + Notification.flagsToString(mOriginalFlags));
pw.println(prefix + "pri=" + notification.priority);
pw.println(prefix + "key=" + getSbn().getKey());
pw.println(prefix + "seen=" + mStats.hasSeen());
@@ -538,8 +538,7 @@
pw.println(prefix + "mInterruptionTimeMs=" + mInterruptionTimeMs);
pw.println(prefix + "mSuppressedVisualEffects= " + mSuppressedVisualEffects);
if (mPreChannelsNotification) {
- pw.println(prefix + String.format("defaults=0x%08x flags=0x%08x",
- notification.defaults, notification.flags));
+ pw.println(prefix + "defaults=" + Notification.defaultsToString(notification.defaults));
pw.println(prefix + "n.sound=" + notification.sound);
pw.println(prefix + "n.audioStreamType=" + notification.audioStreamType);
pw.println(prefix + "n.audioAttributes=" + notification.audioAttributes);
diff --git a/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java b/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java
index 8f6aa95..99401a1 100644
--- a/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java
+++ b/services/core/java/com/android/server/ondeviceintelligence/OnDeviceIntelligenceManagerService.java
@@ -207,8 +207,9 @@
return;
}
ensureRemoteIntelligenceServiceInitialized();
+ int callerUid = Binder.getCallingUid();
mRemoteOnDeviceIntelligenceService.run(
- service -> service.getFeature(Binder.getCallingUid(), id, featureCallback));
+ service -> service.getFeature(callerUid, id, featureCallback));
}
@Override
@@ -227,8 +228,9 @@
return;
}
ensureRemoteIntelligenceServiceInitialized();
+ int callerUid = Binder.getCallingUid();
mRemoteOnDeviceIntelligenceService.run(
- service -> service.listFeatures(Binder.getCallingUid(),
+ service -> service.listFeatures(callerUid,
listFeaturesCallback));
}
@@ -250,8 +252,9 @@
return;
}
ensureRemoteIntelligenceServiceInitialized();
+ int callerUid = Binder.getCallingUid();
mRemoteOnDeviceIntelligenceService.run(
- service -> service.getFeatureDetails(Binder.getCallingUid(), feature,
+ service -> service.getFeatureDetails(callerUid, feature,
featureDetailsCallback));
}
@@ -272,8 +275,9 @@
PersistableBundle.EMPTY);
}
ensureRemoteIntelligenceServiceInitialized();
+ int callerUid = Binder.getCallingUid();
mRemoteOnDeviceIntelligenceService.run(
- service -> service.requestFeatureDownload(Binder.getCallingUid(), feature,
+ service -> service.requestFeatureDownload(callerUid, feature,
wrapCancellationFuture(cancellationSignalFuture),
downloadCallback));
}
@@ -301,9 +305,9 @@
PersistableBundle.EMPTY);
}
ensureRemoteInferenceServiceInitialized();
-
+ int callerUid = Binder.getCallingUid();
result = mRemoteInferenceService.post(
- service -> service.requestTokenInfo(Binder.getCallingUid(), feature,
+ service -> service.requestTokenInfo(callerUid, feature,
request,
wrapCancellationFuture(cancellationSignalFuture),
wrapWithValidation(tokenInfoCallback)));
@@ -340,8 +344,9 @@
PersistableBundle.EMPTY);
}
ensureRemoteInferenceServiceInitialized();
+ int callerUid = Binder.getCallingUid();
result = mRemoteInferenceService.post(
- service -> service.processRequest(Binder.getCallingUid(), feature,
+ service -> service.processRequest(callerUid, feature,
request,
requestType,
wrapCancellationFuture(cancellationSignalFuture),
@@ -379,8 +384,9 @@
PersistableBundle.EMPTY);
}
ensureRemoteInferenceServiceInitialized();
+ int callerUid = Binder.getCallingUid();
result = mRemoteInferenceService.post(
- service -> service.processRequestStreaming(Binder.getCallingUid(),
+ service -> service.processRequestStreaming(callerUid,
feature,
request, requestType,
wrapCancellationFuture(cancellationSignalFuture),
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index fd16221..b2c6c49 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -461,7 +461,7 @@
final int userId = user == null ? UserHandle.USER_ALL : user.getIdentifier();
// Remember which users are affected, before the installed states are modified
- outInfo.mRemovedUsers = (systemApp || userId == UserHandle.USER_ALL)
+ outInfo.mRemovedUsers = userId == UserHandle.USER_ALL
? ps.queryUsersInstalledOrHasData(allUserHandles)
: new int[]{userId};
outInfo.populateBroadcastUsers(ps);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index e3261bd..bb6708a 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2005,26 +2005,27 @@
public void setUserAdmin(@UserIdInt int userId) {
checkManageUserAndAcrossUsersFullPermission("set user admin");
mUserJourneyLogger.logUserJourneyBegin(userId, USER_JOURNEY_GRANT_ADMIN);
- UserInfo info;
+ UserData user;
synchronized (mPackagesLock) {
synchronized (mUsersLock) {
- info = getUserInfoLU(userId);
- }
- if (info == null) {
- // Exit if no user found with that id,
- mUserJourneyLogger.logNullUserJourneyError(USER_JOURNEY_GRANT_ADMIN,
+ user = getUserDataLU(userId);
+ if (user == null) {
+ // Exit if no user found with that id,
+ mUserJourneyLogger.logNullUserJourneyError(USER_JOURNEY_GRANT_ADMIN,
getCurrentUserId(), userId, /* userType */ "", /* userFlags */ -1);
- return;
- } else if (info.isAdmin()) {
- // Exit if the user is already an Admin.
- mUserJourneyLogger.logUserJourneyFinishWithError(getCurrentUserId(), info,
- USER_JOURNEY_GRANT_ADMIN, ERROR_CODE_USER_ALREADY_AN_ADMIN);
- return;
+ return;
+ } else if (user.info.isAdmin()) {
+ // Exit if the user is already an Admin.
+ mUserJourneyLogger.logUserJourneyFinishWithError(getCurrentUserId(),
+ user.info, USER_JOURNEY_GRANT_ADMIN,
+ ERROR_CODE_USER_ALREADY_AN_ADMIN);
+ return;
+ }
+ user.info.flags ^= UserInfo.FLAG_ADMIN;
+ writeUserLP(user);
}
- info.flags ^= UserInfo.FLAG_ADMIN;
- writeUserLP(getUserDataLU(info.id));
}
- mUserJourneyLogger.logUserJourneyFinishWithError(getCurrentUserId(), info,
+ mUserJourneyLogger.logUserJourneyFinishWithError(getCurrentUserId(), user.info,
USER_JOURNEY_GRANT_ADMIN, ERROR_CODE_UNSPECIFIED);
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 20c5b5f..28254d0 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -462,8 +462,8 @@
}
@Override
- public int getNumRegisteredAttributionSources(int uid) {
- return mAttributionSourceRegistry.getNumRegisteredAttributionSources(uid);
+ public int getRegisteredAttributionSourceCount(int uid) {
+ return mAttributionSourceRegistry.getRegisteredAttributionSourceCount(uid);
}
@Override
@@ -943,7 +943,7 @@
}
}
- public int getNumRegisteredAttributionSources(int uid) {
+ public int getRegisteredAttributionSourceCount(int uid) {
mContext.enforceCallingOrSelfPermission(UPDATE_APP_OPS_STATS,
"getting the number of registered AttributionSources requires "
+ "UPDATE_APP_OPS_STATS");
@@ -952,14 +952,13 @@
System.gc();
System.gc();
synchronized (mLock) {
- int[] numForUid = { 0 };
- mAttributions.forEach((key, value) -> {
- if (value.getUid() == uid) {
- numForUid[0]++;
+ int numForUid = 0;
+ for (Map.Entry<IBinder, AttributionSource> entry : mAttributions.entrySet()) {
+ if (entry.getValue().getUid() == uid) {
+ numForUid++;
}
-
- });
- return numForUid[0];
+ }
+ return numForUid;
}
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b4919a4..db18276 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -76,6 +76,7 @@
import static android.view.contentprotection.flags.Flags.createAccessibilityOverlayAppOpEnabled;
import static com.android.hardware.input.Flags.emojiAndScreenshotKeycodesAvailable;
+import static com.android.server.flags.Flags.newBugreportKeyboardShortcut;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
@@ -466,8 +467,8 @@
// Assigned on main thread, accessed on UI thread
volatile VrManagerInternal mVrManagerInternal;
- /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
- boolean mEnableShiftMenuBugReports = false;
+ /** If true, can use a keyboard shortcut to trigger a bugreport. */
+ boolean mEnableBugReportKeyboardShortcut = false;
/** Controller that supports enabling an AccessibilityService by holding down the volume keys */
private AccessibilityShortcutController mAccessibilityShortcutController;
@@ -2303,7 +2304,7 @@
"PhoneWindowManager.mBroadcastWakeLock");
mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"PhoneWindowManager.mPowerKeyWakeLock");
- mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
+ mEnableBugReportKeyboardShortcut = "1".equals(SystemProperties.get("ro.debuggable"));
mLidKeyboardAccessibility = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lidKeyboardAccessibility);
mLidNavigationAccessibility = mContext.getResources().getInteger(
@@ -2360,8 +2361,7 @@
mDisplayFoldController = DisplayFoldController.create(mContext, DEFAULT_DISPLAY);
- mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(
- Context.ACCESSIBILITY_SERVICE);
+ mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
// register for dock events
IntentFilter filter = new IntentFilter();
@@ -3409,19 +3409,6 @@
switch (keyCode) {
case KeyEvent.KEYCODE_HOME:
return handleHomeShortcuts(focusedToken, event);
- case KeyEvent.KEYCODE_MENU:
- // Hijack modified menu keys for debugging features
- final int chordBug = KeyEvent.META_SHIFT_ON;
-
- if (mEnableShiftMenuBugReports && firstDown
- && (metaState & chordBug) == chordBug) {
- Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
- mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
- null, null, null, 0, null, null);
- logKeyboardSystemsEvent(event, KeyboardLogEvent.TRIGGER_BUG_REPORT);
- return true;
- }
- break;
case KeyEvent.KEYCODE_RECENT_APPS:
if (firstDown) {
showRecentApps(false /* triggeredFromAltTab */);
@@ -3487,6 +3474,19 @@
}
break;
case KeyEvent.KEYCODE_DEL:
+ if (newBugreportKeyboardShortcut()) {
+ if (mEnableBugReportKeyboardShortcut && firstDown
+ && event.isMetaPressed() && event.isCtrlPressed()) {
+ try {
+ mActivityManagerService.requestInteractiveBugReport();
+ } catch (RemoteException e) {
+ Slog.d(TAG, "Error taking bugreport", e);
+ }
+ logKeyboardSystemsEvent(event, KeyboardLogEvent.TRIGGER_BUG_REPORT);
+ return true;
+ }
+ }
+ // fall through
case KeyEvent.KEYCODE_ESCAPE:
if (firstDown && event.isMetaPressed()) {
logKeyboardSystemsEvent(event, KeyboardLogEvent.BACK);
diff --git a/services/core/java/com/android/server/power/hint/Android.bp b/services/core/java/com/android/server/power/hint/Android.bp
index d7dd902..6dadf8f 100644
--- a/services/core/java/com/android/server/power/hint/Android.bp
+++ b/services/core/java/com/android/server/power/hint/Android.bp
@@ -11,3 +11,10 @@
name: "power_hint_flags_lib",
aconfig_declarations: "power_hint_flags",
}
+
+java_aconfig_library {
+ name: "power_hint_flags_lib_host",
+ aconfig_declarations: "power_hint_flags",
+ host_supported: true,
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index 54cb9c9..49c4000 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -19,6 +19,7 @@
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.os.BatteryStats.Uid.NUM_PROCESS_STATE;
+import static android.os.BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS;
import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
@@ -292,7 +293,25 @@
private int[] mCpuPowerBracketMap;
private final CpuPowerStatsCollector mCpuPowerStatsCollector;
private final MobileRadioPowerStatsCollector mMobileRadioPowerStatsCollector;
+ private final WifiPowerStatsCollector mWifiPowerStatsCollector;
private final SparseBooleanArray mPowerStatsCollectorEnabled = new SparseBooleanArray();
+ private final WifiPowerStatsCollector.WifiStatsRetriever mWifiStatsRetriever =
+ new WifiPowerStatsCollector.WifiStatsRetriever() {
+ @Override
+ public void retrieveWifiScanTimes(Callback callback) {
+ synchronized (BatteryStatsImpl.this) {
+ retrieveWifiScanTimesLocked(callback);
+ }
+ }
+
+ @Override
+ public long getWifiActiveDuration() {
+ synchronized (BatteryStatsImpl.this) {
+ return getGlobalWifiRunningTime(mClock.elapsedRealtime() * 1000,
+ STATS_SINCE_CHARGED) / 1000;
+ }
+ }
+ };
public LongSparseArray<SamplingTimer> getKernelMemoryStats() {
return mKernelMemoryStats;
@@ -501,6 +520,8 @@
TimeUnit.MINUTES.toMillis(1));
setPowerStatsThrottlePeriodMillis(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO,
TimeUnit.HOURS.toMillis(1));
+ setPowerStatsThrottlePeriodMillis(BatteryConsumer.POWER_COMPONENT_WIFI,
+ TimeUnit.HOURS.toMillis(1));
}
/**
@@ -1885,11 +1906,12 @@
}
private class PowerStatsCollectorInjector implements CpuPowerStatsCollector.Injector,
- MobileRadioPowerStatsCollector.Injector {
+ MobileRadioPowerStatsCollector.Injector, WifiPowerStatsCollector.Injector {
private PackageManager mPackageManager;
private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
private NetworkStatsManager mNetworkStatsManager;
private TelephonyManager mTelephonyManager;
+ private WifiManager mWifiManager;
void setContext(Context context) {
mPackageManager = context.getPackageManager();
@@ -1897,6 +1919,7 @@
LocalServices.getService(PowerStatsInternal.class));
mNetworkStatsManager = context.getSystemService(NetworkStatsManager.class);
mTelephonyManager = context.getSystemService(TelephonyManager.class);
+ mWifiManager = context.getSystemService(WifiManager.class);
}
@Override
@@ -1950,11 +1973,26 @@
}
@Override
+ public Supplier<NetworkStats> getWifiNetworkStatsSupplier() {
+ return () -> readWifiNetworkStatsLocked(mNetworkStatsManager);
+ }
+
+ @Override
+ public WifiPowerStatsCollector.WifiStatsRetriever getWifiStatsRetriever() {
+ return mWifiStatsRetriever;
+ }
+
+ @Override
public TelephonyManager getTelephonyManager() {
return mTelephonyManager;
}
@Override
+ public WifiManager getWifiManager() {
+ return mWifiManager;
+ }
+
+ @Override
public LongSupplier getCallDurationSupplier() {
return () -> mPhoneOnTimer.getTotalTimeLocked(mClock.elapsedRealtime() * 1000,
STATS_SINCE_CHARGED);
@@ -6354,7 +6392,11 @@
HistoryItem.STATE2_WIFI_ON_FLAG);
mWifiOn = true;
mWifiOnTimer.startRunningLocked(elapsedRealtimeMs);
- scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
+ if (mWifiPowerStatsCollector.isEnabled()) {
+ mWifiPowerStatsCollector.schedule();
+ } else {
+ scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI);
+ }
}
}
@@ -6365,7 +6407,11 @@
HistoryItem.STATE2_WIFI_ON_FLAG);
mWifiOn = false;
mWifiOnTimer.stopRunningLocked(elapsedRealtimeMs);
- scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
+ if (mWifiPowerStatsCollector.isEnabled()) {
+ mWifiPowerStatsCollector.schedule();
+ } else {
+ scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI);
+ }
}
}
@@ -6757,8 +6803,11 @@
.noteWifiRunningLocked(elapsedRealtimeMs);
}
}
-
- scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
+ if (mWifiPowerStatsCollector.isEnabled()) {
+ mWifiPowerStatsCollector.schedule();
+ } else {
+ scheduleSyncExternalStatsLocked("wifi-running", ExternalStatsSync.UPDATE_WIFI);
+ }
} else {
Log.w(TAG, "noteWifiRunningLocked -- called while WIFI running");
}
@@ -6827,7 +6876,11 @@
}
}
- scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
+ if (mWifiPowerStatsCollector.isEnabled()) {
+ mWifiPowerStatsCollector.schedule();
+ } else {
+ scheduleSyncExternalStatsLocked("wifi-stopped", ExternalStatsSync.UPDATE_WIFI);
+ }
} else {
Log.w(TAG, "noteWifiStoppedLocked -- called while WIFI not running");
}
@@ -6842,7 +6895,11 @@
}
mWifiState = wifiState;
mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtimeMs);
- scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
+ if (mWifiPowerStatsCollector.isEnabled()) {
+ mWifiPowerStatsCollector.schedule();
+ } else {
+ scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI);
+ }
}
}
@@ -6965,6 +7022,25 @@
.noteWifiBatchedScanStoppedLocked(elapsedRealtimeMs);
}
+ private void retrieveWifiScanTimesLocked(
+ WifiPowerStatsCollector.WifiStatsRetriever.Callback callback) {
+ long elapsedTimeUs = mClock.elapsedRealtime() * 1000;
+ for (int i = mUidStats.size() - 1; i >= 0; i--) {
+ int uid = mUidStats.keyAt(i);
+ Uid uidStats = mUidStats.valueAt(i);
+ long scanTimeUs = uidStats.getWifiScanTime(elapsedTimeUs, STATS_SINCE_CHARGED);
+ long batchScanTimeUs = 0;
+ for (int bucket = 0; bucket < NUM_WIFI_BATCHED_SCAN_BINS; bucket++) {
+ batchScanTimeUs += uidStats.getWifiBatchedScanTime(bucket, elapsedTimeUs,
+ STATS_SINCE_CHARGED);
+ }
+ if (scanTimeUs != 0 || batchScanTimeUs != 0) {
+ callback.onWifiScanTime(uid, (scanTimeUs + 500) / 1000,
+ (batchScanTimeUs + 500) / 1000);
+ }
+ }
+ }
+
private int mWifiMulticastNesting = 0;
@GuardedBy("this")
@@ -11101,6 +11177,11 @@
BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO));
mMobileRadioPowerStatsCollector.addConsumer(this::recordPowerStats);
+ mWifiPowerStatsCollector = new WifiPowerStatsCollector(
+ mPowerStatsCollectorInjector, mBatteryStatsConfig.getPowerStatsThrottlePeriod(
+ BatteryConsumer.POWER_COMPONENT_WIFI));
+ mWifiPowerStatsCollector.addConsumer(this::recordPowerStats);
+
mStartCount++;
initTimersAndCounters();
mOnBattery = mOnBatteryInternal = false;
@@ -12095,10 +12176,10 @@
}
}
if (lastEntry != null) {
- delta.mRxBytes = entry.getRxBytes() - lastEntry.getRxBytes();
- delta.mRxPackets = entry.getRxPackets() - lastEntry.getRxPackets();
- delta.mTxBytes = entry.getTxBytes() - lastEntry.getTxBytes();
- delta.mTxPackets = entry.getTxPackets() - lastEntry.getTxPackets();
+ delta.mRxBytes = Math.max(0, entry.getRxBytes() - lastEntry.getRxBytes());
+ delta.mRxPackets = Math.max(0, entry.getRxPackets() - lastEntry.getRxPackets());
+ delta.mTxBytes = Math.max(0, entry.getTxBytes() - lastEntry.getTxBytes());
+ delta.mTxPackets = Math.max(0, entry.getTxPackets() - lastEntry.getTxPackets());
} else {
delta.mRxBytes = entry.getRxBytes();
delta.mRxPackets = entry.getRxPackets();
@@ -12119,6 +12200,10 @@
public void updateWifiState(@Nullable final WifiActivityEnergyInfo info,
final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs,
@NonNull NetworkStatsManager networkStatsManager) {
+ if (mWifiPowerStatsCollector.isEnabled()) {
+ return;
+ }
+
if (DEBUG_ENERGY) {
synchronized (mWifiNetworkLock) {
Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
@@ -14507,6 +14592,10 @@
mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO));
mMobileRadioPowerStatsCollector.schedule();
+ mWifiPowerStatsCollector.setEnabled(
+ mPowerStatsCollectorEnabled.get(BatteryConsumer.POWER_COMPONENT_WIFI));
+ mWifiPowerStatsCollector.schedule();
+
mSystemReady = true;
}
@@ -14521,6 +14610,8 @@
return mCpuPowerStatsCollector;
case BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO:
return mMobileRadioPowerStatsCollector;
+ case BatteryConsumer.POWER_COMPONENT_WIFI:
+ return mWifiPowerStatsCollector;
}
return null;
}
@@ -16056,6 +16147,7 @@
public void schedulePowerStatsSampleCollection() {
mCpuPowerStatsCollector.forceSchedule();
mMobileRadioPowerStatsCollector.forceSchedule();
+ mWifiPowerStatsCollector.forceSchedule();
}
/**
@@ -16074,6 +16166,7 @@
public void dumpStatsSample(PrintWriter pw) {
mCpuPowerStatsCollector.collectAndDump(pw);
mMobileRadioPowerStatsCollector.collectAndDump(pw);
+ mWifiPowerStatsCollector.collectAndDump(pw);
}
private final Runnable mWriteAsyncRunnable = () -> {
diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
index 97f0986..0d5eabc 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
@@ -87,7 +87,9 @@
mPowerCalculators.add(new PhonePowerCalculator(mPowerProfile));
}
}
- mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile));
+ if (!mPowerStatsExporterEnabled.get(BatteryConsumer.POWER_COMPONENT_WIFI)) {
+ mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile));
+ }
mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile));
mPowerCalculators.add(new SensorPowerCalculator(
mContext.getSystemService(SensorManager.class)));
diff --git a/services/core/java/com/android/server/power/stats/WifiPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/WifiPowerStatsCollector.java
new file mode 100644
index 0000000..6321053
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/WifiPowerStatsCollector.java
@@ -0,0 +1,328 @@
+/*
+ * Copyright (C) 2024 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.power.stats;
+
+import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerType;
+import android.net.NetworkStats;
+import android.net.wifi.WifiManager;
+import android.os.BatteryConsumer;
+import android.os.Handler;
+import android.os.PersistableBundle;
+import android.os.connectivity.WifiActivityEnergyInfo;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.os.Clock;
+import com.android.internal.os.PowerStats;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.function.IntSupplier;
+import java.util.function.Supplier;
+
+public class WifiPowerStatsCollector extends PowerStatsCollector {
+ private static final String TAG = "WifiPowerStatsCollector";
+
+ private static final long WIFI_ACTIVITY_REQUEST_TIMEOUT = 20000;
+
+ private static final long ENERGY_UNSPECIFIED = -1;
+
+ interface WifiStatsRetriever {
+ interface Callback {
+ void onWifiScanTime(int uid, long scanTimeMs, long batchScanTimeMs);
+ }
+
+ void retrieveWifiScanTimes(Callback callback);
+ long getWifiActiveDuration();
+ }
+
+ interface Injector {
+ Handler getHandler();
+ Clock getClock();
+ PowerStatsUidResolver getUidResolver();
+ PackageManager getPackageManager();
+ ConsumedEnergyRetriever getConsumedEnergyRetriever();
+ IntSupplier getVoltageSupplier();
+ Supplier<NetworkStats> getWifiNetworkStatsSupplier();
+ WifiManager getWifiManager();
+ WifiStatsRetriever getWifiStatsRetriever();
+ }
+
+ private final Injector mInjector;
+
+ private WifiPowerStatsLayout mLayout;
+ private boolean mIsInitialized;
+ private boolean mPowerReportingSupported;
+
+ private PowerStats mPowerStats;
+ private long[] mDeviceStats;
+ private volatile WifiManager mWifiManager;
+ private volatile Supplier<NetworkStats> mNetworkStatsSupplier;
+ private volatile WifiStatsRetriever mWifiStatsRetriever;
+ private ConsumedEnergyRetriever mConsumedEnergyRetriever;
+ private IntSupplier mVoltageSupplier;
+ private int[] mEnergyConsumerIds = new int[0];
+ private WifiActivityEnergyInfo mLastWifiActivityInfo =
+ new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0);
+ private NetworkStats mLastNetworkStats;
+ private long[] mLastConsumedEnergyUws;
+ private int mLastVoltageMv;
+
+ private static class WifiScanTimes {
+ public long basicScanTimeMs;
+ public long batchedScanTimeMs;
+ }
+ private final WifiScanTimes mScanTimes = new WifiScanTimes();
+ private final SparseArray<WifiScanTimes> mLastScanTimes = new SparseArray<>();
+ private long mLastWifiActiveDuration;
+
+ public WifiPowerStatsCollector(Injector injector, long throttlePeriodMs) {
+ super(injector.getHandler(), throttlePeriodMs, injector.getUidResolver(),
+ injector.getClock());
+ mInjector = injector;
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ if (enabled) {
+ PackageManager packageManager = mInjector.getPackageManager();
+ super.setEnabled(packageManager != null
+ && packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI));
+ } else {
+ super.setEnabled(false);
+ }
+ }
+
+ private boolean ensureInitialized() {
+ if (mIsInitialized) {
+ return true;
+ }
+
+ if (!isEnabled()) {
+ return false;
+ }
+
+ mConsumedEnergyRetriever = mInjector.getConsumedEnergyRetriever();
+ mVoltageSupplier = mInjector.getVoltageSupplier();
+ mWifiManager = mInjector.getWifiManager();
+ mNetworkStatsSupplier = mInjector.getWifiNetworkStatsSupplier();
+ mWifiStatsRetriever = mInjector.getWifiStatsRetriever();
+ mPowerReportingSupported =
+ mWifiManager != null && mWifiManager.isEnhancedPowerReportingSupported();
+
+ mEnergyConsumerIds = mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.WIFI);
+ mLastConsumedEnergyUws = new long[mEnergyConsumerIds.length];
+ Arrays.fill(mLastConsumedEnergyUws, ENERGY_UNSPECIFIED);
+
+ mLayout = new WifiPowerStatsLayout();
+ mLayout.addDeviceWifiActivity(mPowerReportingSupported);
+ mLayout.addDeviceSectionEnergyConsumers(mEnergyConsumerIds.length);
+ mLayout.addUidNetworkStats();
+ mLayout.addDeviceSectionUsageDuration();
+ mLayout.addDeviceSectionPowerEstimate();
+ mLayout.addUidSectionPowerEstimate();
+
+ PersistableBundle extras = new PersistableBundle();
+ mLayout.toExtras(extras);
+ PowerStats.Descriptor powerStatsDescriptor = new PowerStats.Descriptor(
+ BatteryConsumer.POWER_COMPONENT_WIFI, mLayout.getDeviceStatsArrayLength(),
+ null, 0, mLayout.getUidStatsArrayLength(),
+ extras);
+ mPowerStats = new PowerStats(powerStatsDescriptor);
+ mDeviceStats = mPowerStats.stats;
+
+ mIsInitialized = true;
+ return true;
+ }
+
+ @Override
+ protected PowerStats collectStats() {
+ if (!ensureInitialized()) {
+ return null;
+ }
+
+ if (mPowerReportingSupported) {
+ collectWifiActivityInfo();
+ } else {
+ collectWifiActivityStats();
+ }
+ collectNetworkStats();
+ collectWifiScanTime();
+
+ if (mEnergyConsumerIds.length != 0) {
+ collectEnergyConsumers();
+ }
+
+ return mPowerStats;
+ }
+
+ private void collectWifiActivityInfo() {
+ CompletableFuture<WifiActivityEnergyInfo> immediateFuture = new CompletableFuture<>();
+ mWifiManager.getWifiActivityEnergyInfoAsync(Runnable::run,
+ immediateFuture::complete);
+
+ WifiActivityEnergyInfo activityInfo;
+ try {
+ activityInfo = immediateFuture.get(WIFI_ACTIVITY_REQUEST_TIMEOUT,
+ TimeUnit.MILLISECONDS);
+ } catch (Exception e) {
+ Slog.e(TAG, "Cannot acquire WifiActivityEnergyInfo", e);
+ activityInfo = null;
+ }
+
+ if (activityInfo == null) {
+ return;
+ }
+
+ long rxDuration = activityInfo.getControllerRxDurationMillis()
+ - mLastWifiActivityInfo.getControllerRxDurationMillis();
+ long txDuration = activityInfo.getControllerTxDurationMillis()
+ - mLastWifiActivityInfo.getControllerTxDurationMillis();
+ long scanDuration = activityInfo.getControllerScanDurationMillis()
+ - mLastWifiActivityInfo.getControllerScanDurationMillis();
+ long idleDuration = activityInfo.getControllerIdleDurationMillis()
+ - mLastWifiActivityInfo.getControllerIdleDurationMillis();
+
+ mLayout.setDeviceRxTime(mDeviceStats, rxDuration);
+ mLayout.setDeviceTxTime(mDeviceStats, txDuration);
+ mLayout.setDeviceScanTime(mDeviceStats, scanDuration);
+ mLayout.setDeviceIdleTime(mDeviceStats, idleDuration);
+
+ mPowerStats.durationMs = rxDuration + txDuration + scanDuration + idleDuration;
+
+ mLastWifiActivityInfo = activityInfo;
+ }
+
+ private void collectWifiActivityStats() {
+ long duration = mWifiStatsRetriever.getWifiActiveDuration();
+ mLayout.setDeviceActiveTime(mDeviceStats, Math.max(0, duration - mLastWifiActiveDuration));
+ mLastWifiActiveDuration = duration;
+ mPowerStats.durationMs = duration;
+ }
+
+ private void collectNetworkStats() {
+ mPowerStats.uidStats.clear();
+
+ NetworkStats networkStats = mNetworkStatsSupplier.get();
+ if (networkStats == null) {
+ return;
+ }
+
+ List<BatteryStatsImpl.NetworkStatsDelta> delta =
+ BatteryStatsImpl.computeDelta(networkStats, mLastNetworkStats);
+ mLastNetworkStats = networkStats;
+ for (int i = delta.size() - 1; i >= 0; i--) {
+ BatteryStatsImpl.NetworkStatsDelta uidDelta = delta.get(i);
+ long rxBytes = uidDelta.getRxBytes();
+ long txBytes = uidDelta.getTxBytes();
+ long rxPackets = uidDelta.getRxPackets();
+ long txPackets = uidDelta.getTxPackets();
+ if (rxBytes == 0 && txBytes == 0 && rxPackets == 0 && txPackets == 0) {
+ continue;
+ }
+
+ int uid = mUidResolver.mapUid(uidDelta.getUid());
+ long[] stats = mPowerStats.uidStats.get(uid);
+ if (stats == null) {
+ stats = new long[mLayout.getUidStatsArrayLength()];
+ mPowerStats.uidStats.put(uid, stats);
+ mLayout.setUidRxBytes(stats, rxBytes);
+ mLayout.setUidTxBytes(stats, txBytes);
+ mLayout.setUidRxPackets(stats, rxPackets);
+ mLayout.setUidTxPackets(stats, txPackets);
+ } else {
+ mLayout.setUidRxBytes(stats, mLayout.getUidRxBytes(stats) + rxBytes);
+ mLayout.setUidTxBytes(stats, mLayout.getUidTxBytes(stats) + txBytes);
+ mLayout.setUidRxPackets(stats, mLayout.getUidRxPackets(stats) + rxPackets);
+ mLayout.setUidTxPackets(stats, mLayout.getUidTxPackets(stats) + txPackets);
+ }
+ }
+ }
+
+ private void collectWifiScanTime() {
+ mScanTimes.basicScanTimeMs = 0;
+ mScanTimes.batchedScanTimeMs = 0;
+ mWifiStatsRetriever.retrieveWifiScanTimes((uid, scanTimeMs, batchScanTimeMs) -> {
+ WifiScanTimes lastScanTimes = mLastScanTimes.get(uid);
+ if (lastScanTimes == null) {
+ lastScanTimes = new WifiScanTimes();
+ mLastScanTimes.put(uid, lastScanTimes);
+ }
+
+ long scanTimeDelta = Math.max(0, scanTimeMs - lastScanTimes.basicScanTimeMs);
+ long batchScanTimeDelta = Math.max(0,
+ batchScanTimeMs - lastScanTimes.batchedScanTimeMs);
+ if (scanTimeDelta != 0 || batchScanTimeDelta != 0) {
+ mScanTimes.basicScanTimeMs += scanTimeDelta;
+ mScanTimes.batchedScanTimeMs += batchScanTimeDelta;
+ uid = mUidResolver.mapUid(uid);
+ long[] stats = mPowerStats.uidStats.get(uid);
+ if (stats == null) {
+ stats = new long[mLayout.getUidStatsArrayLength()];
+ mPowerStats.uidStats.put(uid, stats);
+ mLayout.setUidScanTime(stats, scanTimeDelta);
+ mLayout.setUidBatchScanTime(stats, batchScanTimeDelta);
+ } else {
+ mLayout.setUidScanTime(stats, mLayout.getUidScanTime(stats) + scanTimeDelta);
+ mLayout.setUidBatchScanTime(stats,
+ mLayout.getUidBatchedScanTime(stats) + batchScanTimeDelta);
+ }
+ }
+ lastScanTimes.basicScanTimeMs = scanTimeMs;
+ lastScanTimes.batchedScanTimeMs = batchScanTimeMs;
+ });
+
+ mLayout.setDeviceBasicScanTime(mDeviceStats, mScanTimes.basicScanTimeMs);
+ mLayout.setDeviceBatchedScanTime(mDeviceStats, mScanTimes.batchedScanTimeMs);
+ }
+
+ private void collectEnergyConsumers() {
+ int voltageMv = mVoltageSupplier.getAsInt();
+ if (voltageMv <= 0) {
+ Slog.wtf(TAG, "Unexpected battery voltage (" + voltageMv
+ + " mV) when querying energy consumers");
+ return;
+ }
+
+ int averageVoltage = mLastVoltageMv != 0 ? (mLastVoltageMv + voltageMv) / 2 : voltageMv;
+ mLastVoltageMv = voltageMv;
+
+ long[] energyUws = mConsumedEnergyRetriever.getConsumedEnergyUws(mEnergyConsumerIds);
+ if (energyUws == null) {
+ return;
+ }
+
+ for (int i = energyUws.length - 1; i >= 0; i--) {
+ long energyDelta = mLastConsumedEnergyUws[i] != ENERGY_UNSPECIFIED
+ ? energyUws[i] - mLastConsumedEnergyUws[i] : 0;
+ if (energyDelta < 0) {
+ // Likely, restart of powerstats HAL
+ energyDelta = 0;
+ }
+ mLayout.setConsumedEnergy(mPowerStats.stats, i, uJtoUc(energyDelta, averageVoltage));
+ mLastConsumedEnergyUws[i] = energyUws[i];
+ }
+ }
+
+ @Override
+ protected void onUidRemoved(int uid) {
+ super.onUidRemoved(uid);
+ mLastScanTimes.remove(uid);
+ }
+}
diff --git a/services/core/java/com/android/server/power/stats/WifiPowerStatsLayout.java b/services/core/java/com/android/server/power/stats/WifiPowerStatsLayout.java
new file mode 100644
index 0000000..0fa6ec6
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/WifiPowerStatsLayout.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2024 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.power.stats;
+
+import android.annotation.NonNull;
+import android.os.PersistableBundle;
+
+import com.android.internal.os.PowerStats;
+
+public class WifiPowerStatsLayout extends PowerStatsLayout {
+ private static final String TAG = "WifiPowerStatsLayout";
+ private static final int UNSPECIFIED = -1;
+ private static final String EXTRA_POWER_REPORTING_SUPPORTED = "prs";
+ private static final String EXTRA_DEVICE_RX_TIME_POSITION = "dt-rx";
+ private static final String EXTRA_DEVICE_TX_TIME_POSITION = "dt-tx";
+ private static final String EXTRA_DEVICE_SCAN_TIME_POSITION = "dt-scan";
+ private static final String EXTRA_DEVICE_BASIC_SCAN_TIME_POSITION = "dt-basic-scan";
+ private static final String EXTRA_DEVICE_BATCHED_SCAN_TIME_POSITION = "dt-batch-scan";
+ private static final String EXTRA_DEVICE_IDLE_TIME_POSITION = "dt-idle";
+ private static final String EXTRA_DEVICE_ACTIVE_TIME_POSITION = "dt-on";
+ private static final String EXTRA_UID_RX_BYTES_POSITION = "urxb";
+ private static final String EXTRA_UID_TX_BYTES_POSITION = "utxb";
+ private static final String EXTRA_UID_RX_PACKETS_POSITION = "urxp";
+ private static final String EXTRA_UID_TX_PACKETS_POSITION = "utxp";
+ private static final String EXTRA_UID_SCAN_TIME_POSITION = "ut-scan";
+ private static final String EXTRA_UID_BATCH_SCAN_TIME_POSITION = "ut-bscan";
+
+ private boolean mPowerReportingSupported;
+ private int mDeviceRxTimePosition;
+ private int mDeviceTxTimePosition;
+ private int mDeviceIdleTimePosition;
+ private int mDeviceScanTimePosition;
+ private int mDeviceBasicScanTimePosition;
+ private int mDeviceBatchedScanTimePosition;
+ private int mDeviceActiveTimePosition;
+ private int mUidRxBytesPosition;
+ private int mUidTxBytesPosition;
+ private int mUidRxPacketsPosition;
+ private int mUidTxPacketsPosition;
+ private int mUidScanTimePosition;
+ private int mUidBatchScanTimePosition;
+
+ WifiPowerStatsLayout() {
+ }
+
+ WifiPowerStatsLayout(@NonNull PowerStats.Descriptor descriptor) {
+ super(descriptor);
+ }
+
+ void addDeviceWifiActivity(boolean powerReportingSupported) {
+ mPowerReportingSupported = powerReportingSupported;
+ if (mPowerReportingSupported) {
+ mDeviceActiveTimePosition = UNSPECIFIED;
+ mDeviceRxTimePosition = addDeviceSection(1);
+ mDeviceTxTimePosition = addDeviceSection(1);
+ mDeviceIdleTimePosition = addDeviceSection(1);
+ mDeviceScanTimePosition = addDeviceSection(1);
+ } else {
+ mDeviceActiveTimePosition = addDeviceSection(1);
+ mDeviceRxTimePosition = UNSPECIFIED;
+ mDeviceTxTimePosition = UNSPECIFIED;
+ mDeviceIdleTimePosition = UNSPECIFIED;
+ mDeviceScanTimePosition = UNSPECIFIED;
+ }
+ mDeviceBasicScanTimePosition = addDeviceSection(1);
+ mDeviceBatchedScanTimePosition = addDeviceSection(1);
+ }
+
+ void addUidNetworkStats() {
+ mUidRxBytesPosition = addUidSection(1);
+ mUidTxBytesPosition = addUidSection(1);
+ mUidRxPacketsPosition = addUidSection(1);
+ mUidTxPacketsPosition = addUidSection(1);
+ mUidScanTimePosition = addUidSection(1);
+ mUidBatchScanTimePosition = addUidSection(1);
+ }
+
+ public boolean isPowerReportingSupported() {
+ return mPowerReportingSupported;
+ }
+
+ public void setDeviceRxTime(long[] stats, long durationMillis) {
+ stats[mDeviceRxTimePosition] = durationMillis;
+ }
+
+ public long getDeviceRxTime(long[] stats) {
+ return stats[mDeviceRxTimePosition];
+ }
+
+ public void setDeviceTxTime(long[] stats, long durationMillis) {
+ stats[mDeviceTxTimePosition] = durationMillis;
+ }
+
+ public long getDeviceTxTime(long[] stats) {
+ return stats[mDeviceTxTimePosition];
+ }
+
+ public void setDeviceScanTime(long[] stats, long durationMillis) {
+ stats[mDeviceScanTimePosition] = durationMillis;
+ }
+
+ public long getDeviceScanTime(long[] stats) {
+ return stats[mDeviceScanTimePosition];
+ }
+
+ public void setDeviceBasicScanTime(long[] stats, long durationMillis) {
+ stats[mDeviceBasicScanTimePosition] = durationMillis;
+ }
+
+ public long getDeviceBasicScanTime(long[] stats) {
+ return stats[mDeviceBasicScanTimePosition];
+ }
+
+ public void setDeviceBatchedScanTime(long[] stats, long durationMillis) {
+ stats[mDeviceBatchedScanTimePosition] = durationMillis;
+ }
+
+ public long getDeviceBatchedScanTime(long[] stats) {
+ return stats[mDeviceBatchedScanTimePosition];
+ }
+
+ public void setDeviceIdleTime(long[] stats, long durationMillis) {
+ stats[mDeviceIdleTimePosition] = durationMillis;
+ }
+
+ public long getDeviceIdleTime(long[] stats) {
+ return stats[mDeviceIdleTimePosition];
+ }
+
+ public void setDeviceActiveTime(long[] stats, long durationMillis) {
+ stats[mDeviceActiveTimePosition] = durationMillis;
+ }
+
+ public long getDeviceActiveTime(long[] stats) {
+ return stats[mDeviceActiveTimePosition];
+ }
+
+ public void setUidRxBytes(long[] stats, long count) {
+ stats[mUidRxBytesPosition] = count;
+ }
+
+ public long getUidRxBytes(long[] stats) {
+ return stats[mUidRxBytesPosition];
+ }
+
+ public void setUidTxBytes(long[] stats, long count) {
+ stats[mUidTxBytesPosition] = count;
+ }
+
+ public long getUidTxBytes(long[] stats) {
+ return stats[mUidTxBytesPosition];
+ }
+
+ public void setUidRxPackets(long[] stats, long count) {
+ stats[mUidRxPacketsPosition] = count;
+ }
+
+ public long getUidRxPackets(long[] stats) {
+ return stats[mUidRxPacketsPosition];
+ }
+
+ public void setUidTxPackets(long[] stats, long count) {
+ stats[mUidTxPacketsPosition] = count;
+ }
+
+ public long getUidTxPackets(long[] stats) {
+ return stats[mUidTxPacketsPosition];
+ }
+
+ public void setUidScanTime(long[] stats, long count) {
+ stats[mUidScanTimePosition] = count;
+ }
+
+ public long getUidScanTime(long[] stats) {
+ return stats[mUidScanTimePosition];
+ }
+
+ public void setUidBatchScanTime(long[] stats, long count) {
+ stats[mUidBatchScanTimePosition] = count;
+ }
+
+ public long getUidBatchedScanTime(long[] stats) {
+ return stats[mUidBatchScanTimePosition];
+ }
+
+ /**
+ * Copies the elements of the stats array layout into <code>extras</code>
+ */
+ public void toExtras(PersistableBundle extras) {
+ super.toExtras(extras);
+ extras.putBoolean(EXTRA_POWER_REPORTING_SUPPORTED, mPowerReportingSupported);
+ extras.putInt(EXTRA_DEVICE_RX_TIME_POSITION, mDeviceRxTimePosition);
+ extras.putInt(EXTRA_DEVICE_TX_TIME_POSITION, mDeviceTxTimePosition);
+ extras.putInt(EXTRA_DEVICE_SCAN_TIME_POSITION, mDeviceScanTimePosition);
+ extras.putInt(EXTRA_DEVICE_BASIC_SCAN_TIME_POSITION, mDeviceBasicScanTimePosition);
+ extras.putInt(EXTRA_DEVICE_BATCHED_SCAN_TIME_POSITION, mDeviceBatchedScanTimePosition);
+ extras.putInt(EXTRA_DEVICE_IDLE_TIME_POSITION, mDeviceIdleTimePosition);
+ extras.putInt(EXTRA_DEVICE_ACTIVE_TIME_POSITION, mDeviceActiveTimePosition);
+ extras.putInt(EXTRA_UID_RX_BYTES_POSITION, mUidRxBytesPosition);
+ extras.putInt(EXTRA_UID_TX_BYTES_POSITION, mUidTxBytesPosition);
+ extras.putInt(EXTRA_UID_RX_PACKETS_POSITION, mUidRxPacketsPosition);
+ extras.putInt(EXTRA_UID_TX_PACKETS_POSITION, mUidTxPacketsPosition);
+ extras.putInt(EXTRA_UID_SCAN_TIME_POSITION, mUidScanTimePosition);
+ extras.putInt(EXTRA_UID_BATCH_SCAN_TIME_POSITION, mUidBatchScanTimePosition);
+ }
+
+ /**
+ * Retrieves elements of the stats array layout from <code>extras</code>
+ */
+ public void fromExtras(PersistableBundle extras) {
+ super.fromExtras(extras);
+ mPowerReportingSupported = extras.getBoolean(EXTRA_POWER_REPORTING_SUPPORTED);
+ mDeviceRxTimePosition = extras.getInt(EXTRA_DEVICE_RX_TIME_POSITION);
+ mDeviceTxTimePosition = extras.getInt(EXTRA_DEVICE_TX_TIME_POSITION);
+ mDeviceScanTimePosition = extras.getInt(EXTRA_DEVICE_SCAN_TIME_POSITION);
+ mDeviceBasicScanTimePosition = extras.getInt(EXTRA_DEVICE_BASIC_SCAN_TIME_POSITION);
+ mDeviceBatchedScanTimePosition = extras.getInt(EXTRA_DEVICE_BATCHED_SCAN_TIME_POSITION);
+ mDeviceIdleTimePosition = extras.getInt(EXTRA_DEVICE_IDLE_TIME_POSITION);
+ mDeviceActiveTimePosition = extras.getInt(EXTRA_DEVICE_ACTIVE_TIME_POSITION);
+ mUidRxBytesPosition = extras.getInt(EXTRA_UID_RX_BYTES_POSITION);
+ mUidTxBytesPosition = extras.getInt(EXTRA_UID_TX_BYTES_POSITION);
+ mUidRxPacketsPosition = extras.getInt(EXTRA_UID_RX_PACKETS_POSITION);
+ mUidTxPacketsPosition = extras.getInt(EXTRA_UID_TX_PACKETS_POSITION);
+ mUidScanTimePosition = extras.getInt(EXTRA_UID_SCAN_TIME_POSITION);
+ mUidBatchScanTimePosition = extras.getInt(EXTRA_UID_BATCH_SCAN_TIME_POSITION);
+ }
+}
diff --git a/services/core/java/com/android/server/power/stats/WifiPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/WifiPowerStatsProcessor.java
new file mode 100644
index 0000000..5e9cc40
--- /dev/null
+++ b/services/core/java/com/android/server/power/stats/WifiPowerStatsProcessor.java
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2024 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.power.stats;
+
+import android.util.Slog;
+
+import com.android.internal.os.PowerProfile;
+import com.android.internal.os.PowerStats;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class WifiPowerStatsProcessor extends PowerStatsProcessor {
+ private static final String TAG = "WifiPowerStatsProcessor";
+ private static final boolean DEBUG = false;
+
+ private final UsageBasedPowerEstimator mRxPowerEstimator;
+ private final UsageBasedPowerEstimator mTxPowerEstimator;
+ private final UsageBasedPowerEstimator mIdlePowerEstimator;
+
+ private final UsageBasedPowerEstimator mActivePowerEstimator;
+ private final UsageBasedPowerEstimator mScanPowerEstimator;
+ private final UsageBasedPowerEstimator mBatchedScanPowerEstimator;
+
+ private PowerStats.Descriptor mLastUsedDescriptor;
+ private WifiPowerStatsLayout mStatsLayout;
+ // Sequence of steps for power estimation and intermediate results.
+ private PowerEstimationPlan mPlan;
+
+ private long[] mTmpDeviceStatsArray;
+ private long[] mTmpUidStatsArray;
+ private boolean mHasWifiPowerController;
+
+ public WifiPowerStatsProcessor(PowerProfile powerProfile) {
+ mRxPowerEstimator = new UsageBasedPowerEstimator(
+ powerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX));
+ mTxPowerEstimator = new UsageBasedPowerEstimator(
+ powerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX));
+ mIdlePowerEstimator = new UsageBasedPowerEstimator(
+ powerProfile.getAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE));
+ mActivePowerEstimator = new UsageBasedPowerEstimator(
+ powerProfile.getAveragePower(PowerProfile.POWER_WIFI_ACTIVE));
+ mScanPowerEstimator = new UsageBasedPowerEstimator(
+ powerProfile.getAveragePower(PowerProfile.POWER_WIFI_SCAN));
+ mBatchedScanPowerEstimator = new UsageBasedPowerEstimator(
+ powerProfile.getAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN));
+ }
+
+ private static class Intermediates {
+ /**
+ * Estimated power for the RX state.
+ */
+ public double rxPower;
+ /**
+ * Estimated power for the TX state.
+ */
+ public double txPower;
+ /**
+ * Estimated power in the SCAN state
+ */
+ public double scanPower;
+ /**
+ * Estimated power for IDLE, SCAN states.
+ */
+ public double idlePower;
+ /**
+ * Number of received packets
+ */
+ public long rxPackets;
+ /**
+ * Number of transmitted packets
+ */
+ public long txPackets;
+ /**
+ * Total duration of unbatched scans across all UIDs.
+ */
+ public long basicScanDuration;
+ /**
+ * Estimated power in the unbatched SCAN state
+ */
+ public double basicScanPower;
+ /**
+ * Total duration of batched scans across all UIDs.
+ */
+ public long batchedScanDuration;
+ /**
+ * Estimated power in the BATCHED SCAN state
+ */
+ public double batchedScanPower;
+ /**
+ * Estimated total power when active; used only in the absence of WiFiManager power
+ * reporting.
+ */
+ public double activePower;
+ /**
+ * Measured consumed energy from power monitoring hardware (micro-coulombs)
+ */
+ public long consumedEnergy;
+ }
+
+ @Override
+ void finish(PowerComponentAggregatedPowerStats stats) {
+ if (stats.getPowerStatsDescriptor() == null) {
+ return;
+ }
+
+ unpackPowerStatsDescriptor(stats.getPowerStatsDescriptor());
+
+ if (mPlan == null) {
+ mPlan = new PowerEstimationPlan(stats.getConfig());
+ }
+
+ for (int i = mPlan.deviceStateEstimations.size() - 1; i >= 0; i--) {
+ DeviceStateEstimation estimation = mPlan.deviceStateEstimations.get(i);
+ Intermediates intermediates = new Intermediates();
+ estimation.intermediates = intermediates;
+ computeDevicePowerEstimates(stats, estimation.stateValues, intermediates);
+ }
+
+ double ratio = 1.0;
+ if (mStatsLayout.getEnergyConsumerCount() != 0) {
+ ratio = computeEstimateAdjustmentRatioUsingConsumedEnergy();
+ if (ratio != 1) {
+ for (int i = mPlan.deviceStateEstimations.size() - 1; i >= 0; i--) {
+ DeviceStateEstimation estimation = mPlan.deviceStateEstimations.get(i);
+ adjustDevicePowerEstimates(stats, estimation.stateValues,
+ (Intermediates) estimation.intermediates, ratio);
+ }
+ }
+ }
+
+ combineDeviceStateEstimates();
+
+ ArrayList<Integer> uids = new ArrayList<>();
+ stats.collectUids(uids);
+ if (!uids.isEmpty()) {
+ for (int uid : uids) {
+ for (int i = 0; i < mPlan.uidStateEstimates.size(); i++) {
+ computeUidActivityTotals(stats, uid, mPlan.uidStateEstimates.get(i));
+ }
+ }
+
+ for (int uid : uids) {
+ for (int i = 0; i < mPlan.uidStateEstimates.size(); i++) {
+ computeUidPowerEstimates(stats, uid, mPlan.uidStateEstimates.get(i));
+ }
+ }
+ }
+ mPlan.resetIntermediates();
+ }
+
+ private void unpackPowerStatsDescriptor(PowerStats.Descriptor descriptor) {
+ if (descriptor.equals(mLastUsedDescriptor)) {
+ return;
+ }
+
+ mLastUsedDescriptor = descriptor;
+ mStatsLayout = new WifiPowerStatsLayout(descriptor);
+ mTmpDeviceStatsArray = new long[descriptor.statsArrayLength];
+ mTmpUidStatsArray = new long[descriptor.uidStatsArrayLength];
+ mHasWifiPowerController = mStatsLayout.isPowerReportingSupported();
+ }
+
+ /**
+ * Compute power estimates using the power profile.
+ */
+ private void computeDevicePowerEstimates(PowerComponentAggregatedPowerStats stats,
+ int[] deviceStates, Intermediates intermediates) {
+ if (!stats.getDeviceStats(mTmpDeviceStatsArray, deviceStates)) {
+ return;
+ }
+
+ for (int i = mStatsLayout.getEnergyConsumerCount() - 1; i >= 0; i--) {
+ intermediates.consumedEnergy += mStatsLayout.getConsumedEnergy(mTmpDeviceStatsArray, i);
+ }
+
+ intermediates.basicScanDuration =
+ mStatsLayout.getDeviceBasicScanTime(mTmpDeviceStatsArray);
+ intermediates.batchedScanDuration =
+ mStatsLayout.getDeviceBatchedScanTime(mTmpDeviceStatsArray);
+ if (mHasWifiPowerController) {
+ intermediates.rxPower = mRxPowerEstimator.calculatePower(
+ mStatsLayout.getDeviceRxTime(mTmpDeviceStatsArray));
+ intermediates.txPower = mTxPowerEstimator.calculatePower(
+ mStatsLayout.getDeviceTxTime(mTmpDeviceStatsArray));
+ intermediates.scanPower = mScanPowerEstimator.calculatePower(
+ mStatsLayout.getDeviceScanTime(mTmpDeviceStatsArray));
+ intermediates.idlePower = mIdlePowerEstimator.calculatePower(
+ mStatsLayout.getDeviceIdleTime(mTmpDeviceStatsArray));
+ mStatsLayout.setDevicePowerEstimate(mTmpDeviceStatsArray,
+ intermediates.rxPower + intermediates.txPower + intermediates.scanPower
+ + intermediates.idlePower);
+ } else {
+ intermediates.activePower = mActivePowerEstimator.calculatePower(
+ mStatsLayout.getDeviceActiveTime(mTmpDeviceStatsArray));
+ intermediates.basicScanPower =
+ mScanPowerEstimator.calculatePower(intermediates.basicScanDuration);
+ intermediates.batchedScanPower =
+ mBatchedScanPowerEstimator.calculatePower(intermediates.batchedScanDuration);
+ mStatsLayout.setDevicePowerEstimate(mTmpDeviceStatsArray,
+ intermediates.activePower + intermediates.basicScanPower
+ + intermediates.batchedScanPower);
+ }
+
+ stats.setDeviceStats(deviceStates, mTmpDeviceStatsArray);
+ }
+
+ /**
+ * Compute an adjustment ratio using the total power estimated using the power profile
+ * and the total power measured by hardware.
+ */
+ private double computeEstimateAdjustmentRatioUsingConsumedEnergy() {
+ long totalConsumedEnergy = 0;
+ double totalPower = 0;
+
+ for (int i = mPlan.deviceStateEstimations.size() - 1; i >= 0; i--) {
+ Intermediates intermediates =
+ (Intermediates) mPlan.deviceStateEstimations.get(i).intermediates;
+ if (mHasWifiPowerController) {
+ totalPower += intermediates.rxPower + intermediates.txPower
+ + intermediates.scanPower + intermediates.idlePower;
+ } else {
+ totalPower += intermediates.activePower + intermediates.basicScanPower
+ + intermediates.batchedScanPower;
+ }
+ totalConsumedEnergy += intermediates.consumedEnergy;
+ }
+
+ if (totalPower == 0) {
+ return 1;
+ }
+
+ return uCtoMah(totalConsumedEnergy) / totalPower;
+ }
+
+ /**
+ * Uniformly apply the same adjustment to all power estimates in order to ensure that the total
+ * estimated power matches the measured consumed power. We are not claiming that all
+ * averages captured in the power profile have to be off by the same percentage in reality.
+ */
+ private void adjustDevicePowerEstimates(PowerComponentAggregatedPowerStats stats,
+ int[] deviceStates, Intermediates intermediates, double ratio) {
+ double adjutedPower;
+ if (mHasWifiPowerController) {
+ intermediates.rxPower *= ratio;
+ intermediates.txPower *= ratio;
+ intermediates.scanPower *= ratio;
+ intermediates.idlePower *= ratio;
+ adjutedPower = intermediates.rxPower + intermediates.txPower + intermediates.scanPower
+ + intermediates.idlePower;
+ } else {
+ intermediates.activePower *= ratio;
+ intermediates.basicScanPower *= ratio;
+ intermediates.batchedScanPower *= ratio;
+ adjutedPower = intermediates.activePower + intermediates.basicScanPower
+ + intermediates.batchedScanPower;
+ }
+
+ if (!stats.getDeviceStats(mTmpDeviceStatsArray, deviceStates)) {
+ return;
+ }
+
+ mStatsLayout.setDevicePowerEstimate(mTmpDeviceStatsArray, adjutedPower);
+ stats.setDeviceStats(deviceStates, mTmpDeviceStatsArray);
+ }
+
+ /**
+ * Combine power estimates before distributing them proportionally to UIDs.
+ */
+ private void combineDeviceStateEstimates() {
+ for (int i = mPlan.combinedDeviceStateEstimations.size() - 1; i >= 0; i--) {
+ CombinedDeviceStateEstimate cdse = mPlan.combinedDeviceStateEstimations.get(i);
+ Intermediates
+ cdseIntermediates = new Intermediates();
+ cdse.intermediates = cdseIntermediates;
+ List<DeviceStateEstimation> deviceStateEstimations = cdse.deviceStateEstimations;
+ for (int j = deviceStateEstimations.size() - 1; j >= 0; j--) {
+ DeviceStateEstimation dse = deviceStateEstimations.get(j);
+ Intermediates intermediates = (Intermediates) dse.intermediates;
+ if (mHasWifiPowerController) {
+ cdseIntermediates.rxPower += intermediates.rxPower;
+ cdseIntermediates.txPower += intermediates.txPower;
+ cdseIntermediates.scanPower += intermediates.scanPower;
+ cdseIntermediates.idlePower += intermediates.idlePower;
+ } else {
+ cdseIntermediates.activePower += intermediates.activePower;
+ cdseIntermediates.basicScanPower += intermediates.basicScanPower;
+ cdseIntermediates.batchedScanPower += intermediates.batchedScanPower;
+ }
+ cdseIntermediates.basicScanDuration += intermediates.basicScanDuration;
+ cdseIntermediates.batchedScanDuration += intermediates.batchedScanDuration;
+ cdseIntermediates.consumedEnergy += intermediates.consumedEnergy;
+ }
+ }
+ }
+
+ private void computeUidActivityTotals(PowerComponentAggregatedPowerStats stats, int uid,
+ UidStateEstimate uidStateEstimate) {
+ Intermediates intermediates =
+ (Intermediates) uidStateEstimate.combinedDeviceStateEstimate.intermediates;
+ for (UidStateProportionalEstimate proportionalEstimate :
+ uidStateEstimate.proportionalEstimates) {
+ if (!stats.getUidStats(mTmpUidStatsArray, uid, proportionalEstimate.stateValues)) {
+ continue;
+ }
+
+ intermediates.rxPackets += mStatsLayout.getUidRxPackets(mTmpUidStatsArray);
+ intermediates.txPackets += mStatsLayout.getUidTxPackets(mTmpUidStatsArray);
+ }
+ }
+
+ private void computeUidPowerEstimates(PowerComponentAggregatedPowerStats stats, int uid,
+ UidStateEstimate uidStateEstimate) {
+ Intermediates intermediates =
+ (Intermediates) uidStateEstimate.combinedDeviceStateEstimate.intermediates;
+ for (UidStateProportionalEstimate proportionalEstimate :
+ uidStateEstimate.proportionalEstimates) {
+ if (!stats.getUidStats(mTmpUidStatsArray, uid, proportionalEstimate.stateValues)) {
+ continue;
+ }
+
+ double power = 0;
+ if (mHasWifiPowerController) {
+ if (intermediates.rxPackets != 0) {
+ power += intermediates.rxPower * mStatsLayout.getUidRxPackets(mTmpUidStatsArray)
+ / intermediates.rxPackets;
+ }
+ if (intermediates.txPackets != 0) {
+ power += intermediates.txPower * mStatsLayout.getUidTxPackets(mTmpUidStatsArray)
+ / intermediates.txPackets;
+ }
+ long totalScanDuration =
+ intermediates.basicScanDuration + intermediates.batchedScanDuration;
+ if (totalScanDuration != 0) {
+ long scanDuration = mStatsLayout.getUidScanTime(mTmpUidStatsArray)
+ + mStatsLayout.getUidBatchedScanTime(mTmpUidStatsArray);
+ power += intermediates.scanPower * scanDuration / totalScanDuration;
+ }
+ } else {
+ long totalPackets = intermediates.rxPackets + intermediates.txPackets;
+ if (totalPackets != 0) {
+ long packets = mStatsLayout.getUidRxPackets(mTmpUidStatsArray)
+ + mStatsLayout.getUidTxPackets(mTmpUidStatsArray);
+ power += intermediates.activePower * packets / totalPackets;
+ }
+
+ if (intermediates.basicScanDuration != 0) {
+ long scanDuration = mStatsLayout.getUidScanTime(mTmpUidStatsArray);
+ power += intermediates.basicScanPower * scanDuration
+ / intermediates.basicScanDuration;
+ }
+
+ if (intermediates.batchedScanDuration != 0) {
+ long batchedScanDuration = mStatsLayout.getUidBatchedScanTime(
+ mTmpUidStatsArray);
+ power += intermediates.batchedScanPower * batchedScanDuration
+ / intermediates.batchedScanDuration;
+ }
+ }
+ mStatsLayout.setUidPowerEstimate(mTmpUidStatsArray, power);
+ stats.setUidStats(uid, proportionalEstimate.stateValues, mTmpUidStatsArray);
+
+ if (DEBUG) {
+ Slog.d(TAG, "UID: " + uid
+ + " states: " + Arrays.toString(proportionalEstimate.stateValues)
+ + " stats: " + Arrays.toString(mTmpUidStatsArray)
+ + " rx: " + mStatsLayout.getUidRxPackets(mTmpUidStatsArray)
+ + " rx-power: " + intermediates.rxPower
+ + " rx-packets: " + intermediates.rxPackets
+ + " tx: " + mStatsLayout.getUidTxPackets(mTmpUidStatsArray)
+ + " tx-power: " + intermediates.txPower
+ + " tx-packets: " + intermediates.txPackets
+ + " power: " + power);
+ }
+ }
+ }
+
+ @Override
+ String deviceStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
+ unpackPowerStatsDescriptor(descriptor);
+ if (mHasWifiPowerController) {
+ return "rx: " + mStatsLayout.getDeviceRxTime(stats)
+ + " tx: " + mStatsLayout.getDeviceTxTime(stats)
+ + " scan: " + mStatsLayout.getDeviceScanTime(stats)
+ + " idle: " + mStatsLayout.getDeviceIdleTime(stats)
+ + " power: " + mStatsLayout.getDevicePowerEstimate(stats);
+ } else {
+ return "active: " + mStatsLayout.getDeviceActiveTime(stats)
+ + " scan: " + mStatsLayout.getDeviceBasicScanTime(stats)
+ + " batched-scan: " + mStatsLayout.getDeviceBatchedScanTime(stats)
+ + " power: " + mStatsLayout.getDevicePowerEstimate(stats);
+ }
+ }
+
+ @Override
+ String stateStatsToString(PowerStats.Descriptor descriptor, int key, long[] stats) {
+ // Unsupported for this power component
+ return null;
+ }
+
+ @Override
+ String uidStatsToString(PowerStats.Descriptor descriptor, long[] stats) {
+ unpackPowerStatsDescriptor(descriptor);
+ return "rx: " + mStatsLayout.getUidRxPackets(stats)
+ + " tx: " + mStatsLayout.getUidTxPackets(stats)
+ + " scan: " + mStatsLayout.getUidScanTime(stats)
+ + " batched-scan: " + mStatsLayout.getUidBatchedScanTime(stats)
+ + " power: " + mStatsLayout.getUidPowerEstimate(stats);
+ }
+}
diff --git a/services/core/java/com/android/server/power/stats/flags.aconfig b/services/core/java/com/android/server/power/stats/flags.aconfig
index 54ae84f4..9283fe9 100644
--- a/services/core/java/com/android/server/power/stats/flags.aconfig
+++ b/services/core/java/com/android/server/power/stats/flags.aconfig
@@ -30,3 +30,10 @@
description: "Feature flag for streamlined connectivity battery stats"
bug: "323970018"
}
+
+flag {
+ name: "streamlined_misc_battery_stats"
+ namespace: "backstage_power"
+ description: "Feature flag for streamlined misc (excluding CPU, Cell, Wifi, BT) battery stats"
+ bug: "333941740"
+}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index f925b5f..42efc2d 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -77,6 +77,7 @@
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED;
import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON;
+import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION;
import static android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED;
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
@@ -2119,9 +2120,19 @@
mCameraCompatControlEnabled = mWmService.mContext.getResources()
.getBoolean(R.bool.config_isCameraCompatControlForStretchedIssuesEnabled);
mResolveConfigHint = new TaskFragment.ConfigOverrideHint();
- mResolveConfigHint.mUseLegacyInsetsForStableBounds =
- mWmService.mFlags.mInsetsDecoupledConfiguration
- && !info.isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED);
+ if (mWmService.mFlags.mInsetsDecoupledConfiguration) {
+ // When the stable configuration is the default behavior, override for the legacy apps
+ // without forward override flag.
+ mResolveConfigHint.mUseOverrideInsetsForStableBounds =
+ !info.isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED)
+ && !info.isChangeEnabled(
+ OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION);
+ } else {
+ // When the stable configuration is not the default behavior, forward overriding the
+ // listed apps.
+ mResolveConfigHint.mUseOverrideInsetsForStableBounds =
+ info.isChangeEnabled(OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION);
+ }
mTargetSdk = info.applicationInfo.targetSdkVersion;
@@ -8466,7 +8477,7 @@
mCompatDisplayInsets =
new CompatDisplayInsets(
mDisplayContent, this, letterboxedContainerBounds,
- mResolveConfigHint.mUseLegacyInsetsForStableBounds);
+ mResolveConfigHint.mUseOverrideInsetsForStableBounds);
}
private void clearSizeCompatModeAttributes() {
@@ -8665,15 +8676,14 @@
if (mDisplayContent == null) {
return;
}
- final Rect parentAppBounds = newParentConfiguration.windowConfiguration.getAppBounds();
+ final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
int rotation = newParentConfiguration.windowConfiguration.getRotation();
if (rotation == ROTATION_UNDEFINED && !isFixedRotationTransforming()) {
rotation = mDisplayContent.getRotation();
}
- if (!mResolveConfigHint.mUseLegacyInsetsForStableBounds
- || getCompatDisplayInsets() != null
- || isFloating(parentWindowingMode) || parentAppBounds == null
- || parentAppBounds.isEmpty() || rotation == ROTATION_UNDEFINED) {
+ if (!mResolveConfigHint.mUseOverrideInsetsForStableBounds
+ || getCompatDisplayInsets() != null || isFloating(parentWindowingMode)
+ || rotation == ROTATION_UNDEFINED) {
// If the insets configuration decoupled logic is not enabled for the app, or the app
// already has a compat override, or the context doesn't contain enough info to
// calculate the override, skip the override.
@@ -8692,7 +8702,7 @@
// the value if not calculated yet.
Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
if (outAppBounds == null || outAppBounds.isEmpty()) {
- inOutConfig.windowConfiguration.setAppBounds(parentAppBounds);
+ inOutConfig.windowConfiguration.setAppBounds(parentBounds);
outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
outAppBounds.inset(nonDecorInsets);
}
@@ -8703,14 +8713,11 @@
density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
final int overrideScreenWidthDp = (int) (outAppBounds.width() / density + 0.5f);
- inOutConfig.screenWidthDp =
- Math.min(overrideScreenWidthDp, newParentConfiguration.screenWidthDp);
+ inOutConfig.screenWidthDp = overrideScreenWidthDp;
}
if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
- final int overrideScreenHeightDp =
- (int) (outAppBounds.height() / density + 0.5f);
- inOutConfig.screenHeightDp =
- Math.min(overrideScreenHeightDp, newParentConfiguration.screenHeightDp);
+ final int overrideScreenHeightDp = (int) (outAppBounds.height() / density + 0.5f);
+ inOutConfig.screenHeightDp = overrideScreenHeightDp;
}
if (inOutConfig.smallestScreenWidthDp
== Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
@@ -8987,7 +8994,7 @@
if (mDisplayContent == null) {
return true;
}
- if (!mResolveConfigHint.mUseLegacyInsetsForStableBounds) {
+ if (!mResolveConfigHint.mUseOverrideInsetsForStableBounds) {
// No insets should be considered any more.
return true;
}
@@ -9006,7 +9013,7 @@
final Task task = getTask();
task.calculateInsetFrames(outNonDecorBounds /* outNonDecorBounds */,
outStableBounds /* outStableBounds */, parentBounds /* bounds */, di,
- mResolveConfigHint.mUseLegacyInsetsForStableBounds);
+ mResolveConfigHint.mUseOverrideInsetsForStableBounds);
final int orientationWithInsets = outStableBounds.height() >= outStableBounds.width()
? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
// If orientation does not match the orientation with insets applied, then a
@@ -9063,7 +9070,7 @@
getResolvedOverrideConfiguration().windowConfiguration.getBounds();
final int stableBoundsOrientation = stableBounds.width() > stableBounds.height()
? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT;
- final int parentOrientation = mResolveConfigHint.mUseLegacyInsetsForStableBounds
+ final int parentOrientation = mResolveConfigHint.mUseOverrideInsetsForStableBounds
? stableBoundsOrientation : newParentConfig.orientation;
// If the activity requires a different orientation (either by override or activityInfo),
@@ -9088,7 +9095,7 @@
return;
}
- final Rect parentAppBounds = mResolveConfigHint.mUseLegacyInsetsForStableBounds
+ final Rect parentAppBounds = mResolveConfigHint.mUseOverrideInsetsForStableBounds
? outNonDecorBounds : newParentConfig.windowConfiguration.getAppBounds();
// TODO(b/182268157): Explore using only one type of parentBoundsWithInsets, either app
// bounds or stable bounds to unify aspect ratio logic.
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index a739e57..b3c43bc 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3736,6 +3736,14 @@
return false;
}
+ // If the app is using auto-enter, and it explicitly requests entering PiP while pausing,
+ // return false immediately since auto-enter should take in place instead.
+ if (fromClient && r.isState(PAUSING) && params.isAutoEnterEnabled()) {
+ Slog.w(TAG, "Skip client enterPictureInPictureMode request while pausing,"
+ + " auto-enter-pip is enabled");
+ return false;
+ }
+
if (isPip2ExperimentEnabled()) {
// If PiP2 flag is on and request to enter PiP comes in,
// we request a direct transition TRANSIT_PIP from Shell to get the right entry bounds.
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 430232c..c74284e 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -2311,8 +2311,12 @@
mService.setLastResumedActivityUncheckLocked(mTopResumedActivity, reason);
}
scheduleTopResumedActivityStateIfNeeded();
-
- mService.updateTopApp(mTopResumedActivity);
+ // If the device is not sleeping and there is no top resumed, do not update top app because
+ // it may be an intermediate state while moving a task to front. The actual top will be set
+ // when TaskFragment#setResumedActivity is called.
+ if (mTopResumedActivity != null || mService.isSleepingLocked()) {
+ mService.updateTopApp(mTopResumedActivity);
+ }
return mTopResumedActivity;
}
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 4a97128..afcf364 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -21,6 +21,7 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.view.Display.TYPE_EXTERNAL;
import static android.view.Display.TYPE_OVERLAY;
+import static android.view.Display.TYPE_VIRTUAL;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
@@ -1794,20 +1795,36 @@
}
}
+ @VisibleForTesting
+ int getDemoUserRotationOverride() {
+ return SystemProperties.getInt("persist.demo.userrotation", Surface.ROTATION_0);
+ }
+
+ @VisibleForTesting
+ @NonNull
+ String getDemoUserRotationPackage() {
+ return SystemProperties.get("persist.demo.userrotation.package_name");
+ }
+
@Surface.Rotation
private int getUserRotationOverride() {
- final int userRotationOverride = SystemProperties.getInt("persist.demo.userrotation",
- Surface.ROTATION_0);
+ final int userRotationOverride = getDemoUserRotationOverride();
if (userRotationOverride == Surface.ROTATION_0) {
return userRotationOverride;
}
- final var display = mDisplayContent.mDisplay;
+ final var display = mDisplayContent.getDisplay();
if (display.getType() == TYPE_EXTERNAL || display.getType() == TYPE_OVERLAY) {
- // TODO b/329442350 add chromecast virtual displays here
return userRotationOverride;
}
+ if (display.getType() == TYPE_VIRTUAL) {
+ final var packageName = getDemoUserRotationPackage();
+ if (!packageName.isEmpty() && packageName.equals(display.getOwnerPackageName())) {
+ return userRotationOverride;
+ }
+ }
+
return Surface.ROTATION_0;
}
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index cb5ad91..da1581e 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -905,13 +905,11 @@
// Note that we check the task rather than the parent as with ActivityEmbedding the parent might
// be a TaskFragment, and its windowing mode is always MULTI_WINDOW, even if the task is
// actually fullscreen.
- private boolean isDisplayFullScreenAndInPosture(DeviceStateController.DeviceState state,
- boolean isTabletop) {
+ private boolean isDisplayFullScreenAndInPosture(boolean isTabletop) {
Task task = mActivityRecord.getTask();
- return mActivityRecord.mDisplayContent != null
- && mActivityRecord.mDisplayContent.getDisplayRotation().isDeviceInPosture(state,
- isTabletop)
- && task != null
+ return mActivityRecord.mDisplayContent != null && task != null
+ && mActivityRecord.mDisplayContent.getDisplayRotation().isDeviceInPosture(
+ DeviceStateController.DeviceState.HALF_FOLDED, isTabletop)
&& task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
}
@@ -939,16 +937,14 @@
}
private boolean isFullScreenAndBookModeEnabled() {
- return isDisplayFullScreenAndInPosture(
- DeviceStateController.DeviceState.HALF_FOLDED, false /* isTabletop */)
+ return isDisplayFullScreenAndInPosture(/* isTabletop */ false)
&& mLetterboxConfiguration.getIsAutomaticReachabilityInBookModeEnabled();
}
float getVerticalPositionMultiplier(Configuration parentConfiguration) {
// Don't check resolved configuration because it may not be updated yet during
// configuration change.
- boolean tabletopMode = isDisplayFullScreenAndInPosture(
- DeviceStateController.DeviceState.HALF_FOLDED, true /* isTabletop */);
+ boolean tabletopMode = isDisplayFullScreenAndInPosture(/* isTabletop */ true);
return isVerticalReachabilityEnabled(parentConfiguration)
// Using the last global dynamic position to avoid "jumps" when moving
// between apps or activities.
@@ -981,16 +977,15 @@
}
private boolean shouldUseSplitScreenAspectRatio(@NonNull Configuration parentConfiguration) {
- final boolean isBookMode = isDisplayFullScreenAndInPosture(
- DeviceStateController.DeviceState.HALF_FOLDED,
- /* isTabletop */ false);
+ final boolean isBookMode = isDisplayFullScreenAndInPosture(/* isTabletop */ false);
final boolean isNotCenteredHorizontally = getHorizontalPositionMultiplier(
parentConfiguration) != LETTERBOX_POSITION_MULTIPLIER_CENTER;
- final boolean isTabletopMode = isDisplayFullScreenAndInPosture(
- DeviceStateController.DeviceState.HALF_FOLDED,
- /* isTabletop */ true);
+ final boolean isTabletopMode = isDisplayFullScreenAndInPosture(/* isTabletop */ true);
+ final boolean isLandscape = isFixedOrientationLandscape(
+ mActivityRecord.getOverrideOrientation());
+
// Don't resize to split screen size when in book mode if letterbox position is centered
- return ((isBookMode && isNotCenteredHorizontally) || isTabletopMode)
+ return (isBookMode && isNotCenteredHorizontally || isTabletopMode && isLandscape)
|| isCameraCompatSplitScreenAspectRatioAllowed()
&& isCameraCompatTreatmentActive();
}
@@ -1647,17 +1642,13 @@
if (isHorizontalReachabilityEnabled()) {
int letterboxPositionForHorizontalReachability = getLetterboxConfiguration()
.getLetterboxPositionForHorizontalReachability(
- isDisplayFullScreenAndInPosture(
- DeviceStateController.DeviceState.HALF_FOLDED,
- false /* isTabletop */));
+ isDisplayFullScreenAndInPosture(/* isTabletop */ false));
positionToLog = letterboxHorizontalReachabilityPositionToLetterboxPosition(
letterboxPositionForHorizontalReachability);
} else if (isVerticalReachabilityEnabled()) {
int letterboxPositionForVerticalReachability = getLetterboxConfiguration()
.getLetterboxPositionForVerticalReachability(
- isDisplayFullScreenAndInPosture(
- DeviceStateController.DeviceState.HALF_FOLDED,
- true /* isTabletop */));
+ isDisplayFullScreenAndInPosture(/* isTabletop */ true));
positionToLog = letterboxVerticalReachabilityPositionToLetterboxPosition(
letterboxPositionForVerticalReachability);
}
diff --git a/services/core/java/com/android/server/wm/PerfettoTransitionTracer.java b/services/core/java/com/android/server/wm/PerfettoTransitionTracer.java
index d08f043..883d27f 100644
--- a/services/core/java/com/android/server/wm/PerfettoTransitionTracer.java
+++ b/services/core/java/com/android/server/wm/PerfettoTransitionTracer.java
@@ -17,7 +17,8 @@
package com.android.server.wm;
import android.annotation.NonNull;
-import android.internal.perfetto.protos.PerfettoTrace;
+import android.internal.perfetto.protos.ShellTransitionOuterClass.ShellTransition;
+import android.internal.perfetto.protos.TracePacketOuterClass.TracePacket;
import android.os.SystemClock;
import android.os.Trace;
import android.tracing.perfetto.DataSourceParams;
@@ -71,18 +72,18 @@
mDataSource.trace((ctx) -> {
final ProtoOutputStream os = ctx.newTracePacket();
- final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
+ final long token = os.start(TracePacket.SHELL_TRANSITION);
- os.write(PerfettoTrace.ShellTransition.ID, transition.getSyncId());
- os.write(PerfettoTrace.ShellTransition.CREATE_TIME_NS,
+ os.write(ShellTransition.ID, transition.getSyncId());
+ os.write(ShellTransition.CREATE_TIME_NS,
transition.mLogger.mCreateTimeNs);
- os.write(PerfettoTrace.ShellTransition.SEND_TIME_NS, transition.mLogger.mSendTimeNs);
- os.write(PerfettoTrace.ShellTransition.START_TRANSACTION_ID,
+ os.write(ShellTransition.SEND_TIME_NS, transition.mLogger.mSendTimeNs);
+ os.write(ShellTransition.START_TRANSACTION_ID,
transition.getStartTransaction().getId());
- os.write(PerfettoTrace.ShellTransition.FINISH_TRANSACTION_ID,
+ os.write(ShellTransition.FINISH_TRANSACTION_ID,
transition.getFinishTransaction().getId());
- os.write(PerfettoTrace.ShellTransition.TYPE, transition.mType);
- os.write(PerfettoTrace.ShellTransition.FLAGS, transition.getFlags());
+ os.write(ShellTransition.TYPE, transition.mType);
+ os.write(ShellTransition.FLAGS, transition.getFlags());
addTransitionTargetsToProto(os, targets);
@@ -114,9 +115,9 @@
mDataSource.trace((ctx) -> {
final ProtoOutputStream os = ctx.newTracePacket();
- final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
- os.write(PerfettoTrace.ShellTransition.ID, transition.getSyncId());
- os.write(PerfettoTrace.ShellTransition.FINISH_TIME_NS,
+ final long token = os.start(TracePacket.SHELL_TRANSITION);
+ os.write(ShellTransition.ID, transition.getSyncId());
+ os.write(ShellTransition.FINISH_TIME_NS,
transition.mLogger.mFinishTimeNs);
os.end(token);
});
@@ -146,9 +147,9 @@
mDataSource.trace((ctx) -> {
final ProtoOutputStream os = ctx.newTracePacket();
- final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
- os.write(PerfettoTrace.ShellTransition.ID, transition.getSyncId());
- os.write(PerfettoTrace.ShellTransition.WM_ABORT_TIME_NS,
+ final long token = os.start(TracePacket.SHELL_TRANSITION);
+ os.write(ShellTransition.ID, transition.getSyncId());
+ os.write(ShellTransition.WM_ABORT_TIME_NS,
transition.mLogger.mAbortTimeNs);
os.end(token);
});
@@ -172,9 +173,9 @@
mDataSource.trace((ctx) -> {
final ProtoOutputStream os = ctx.newTracePacket();
- final long token = os.start(PerfettoTrace.TracePacket.SHELL_TRANSITION);
- os.write(PerfettoTrace.ShellTransition.ID, startingData.mTransitionId);
- os.write(PerfettoTrace.ShellTransition.STARTING_WINDOW_REMOVE_TIME_NS,
+ final long token = os.start(TracePacket.SHELL_TRANSITION);
+ os.write(ShellTransition.ID, startingData.mTransitionId);
+ os.write(ShellTransition.STARTING_WINDOW_REMOVE_TIME_NS,
SystemClock.elapsedRealtimeNanos());
os.end(token);
});
@@ -215,11 +216,11 @@
}
final int windowId = System.identityHashCode(target.mContainer);
- final long token = os.start(PerfettoTrace.ShellTransition.TARGETS);
- os.write(PerfettoTrace.ShellTransition.Target.MODE, target.mReadyMode);
- os.write(PerfettoTrace.ShellTransition.Target.FLAGS, target.mReadyFlags);
- os.write(PerfettoTrace.ShellTransition.Target.LAYER_ID, layerId);
- os.write(PerfettoTrace.ShellTransition.Target.WINDOW_ID, windowId);
+ final long token = os.start(ShellTransition.TARGETS);
+ os.write(ShellTransition.Target.MODE, target.mReadyMode);
+ os.write(ShellTransition.Target.FLAGS, target.mReadyFlags);
+ os.write(ShellTransition.Target.LAYER_ID, layerId);
+ os.write(ShellTransition.Target.WINDOW_ID, windowId);
os.end(token);
}
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 1e88fe4..622a809 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -174,6 +174,7 @@
private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1;
private static final int SET_USER_ACTIVITY_TIMEOUT = 2;
private static final int MSG_SEND_SLEEP_TRANSITION = 3;
+ private static final int PINNED_TASK_ABORT_TIMEOUT = 1000;
static final String TAG_TASKS = TAG + POSTFIX_TASKS;
static final String TAG_STATES = TAG + POSTFIX_STATES;
@@ -295,6 +296,9 @@
};
+ // TODO: b/335866033 Remove the abort PiP on timeout once PiP2 flag is on.
+ @Nullable private Runnable mMaybeAbortPipEnterRunnable = null;
+
private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
static class FindTaskResult implements Predicate<Task> {
@@ -2272,8 +2276,67 @@
resumeFocusedTasksTopActivities();
notifyActivityPipModeChanged(r.getTask(), r);
+
+ if (!isPip2ExperimentEnabled()) {
+ // TODO: b/335866033 Remove the abort PiP on timeout once PiP2 flag is on.
+ // Set up a timeout callback to potentially abort PiP enter if in an inconsistent state.
+ scheduleTimeoutAbortPipEnter(rootTask);
+ }
}
+ private void scheduleTimeoutAbortPipEnter(Task rootTask) {
+ if (mMaybeAbortPipEnterRunnable != null) {
+ // If there is an abort enter PiP check pending already remove it and abort
+ // immediately since we are trying to enter PiP in an inconsistent state
+ mHandler.removeCallbacks(mMaybeAbortPipEnterRunnable);
+ mMaybeAbortPipEnterRunnable.run();
+ }
+ // Snapshot a throwable early on to display the callstack upon abort later on timeout.
+ final Throwable enterPipThrowable = new Throwable();
+ // Set up a timeout to potentially roll back the task change to PINNED mode
+ // by aborting PiP.
+ mMaybeAbortPipEnterRunnable = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mService.mGlobalLock) {
+ if (mTransitionController.inTransition()) {
+ // If this task is a part an active transition aborting PiP might break
+ // it; so run the timeout callback directly once idle.
+
+ final Runnable expectedMaybeAbortAtTimeout = mMaybeAbortPipEnterRunnable;
+ mTransitionController.mStateValidators.add(() -> {
+ // If a second PiP transition comes in, it runs the abort runnable for
+ // the first transition pre-emptively, so we need to avoid calling
+ // the same runnable twice when validating states.
+ if (expectedMaybeAbortAtTimeout != mMaybeAbortPipEnterRunnable) return;
+ mMaybeAbortPipEnterRunnable = null;
+ run();
+ });
+ return;
+ } else {
+ mMaybeAbortPipEnterRunnable = null;
+ }
+ mService.deferWindowLayout();
+ final ActivityRecord top = rootTask.getTopMostActivity();
+ final ActivityManager.RunningTaskInfo beforeTaskInfo =
+ rootTask.getTaskInfo();
+ if (top != null && !top.inPinnedWindowingMode()
+ && rootTask.abortPipEnter(top)) {
+ Slog.wtf(TAG, "Enter PiP was aborted via a scheduled timeout"
+ + "task_state_before=" + beforeTaskInfo
+ + "task_state_after=" + rootTask.getTaskInfo(),
+ enterPipThrowable);
+ }
+ mService.continueWindowLayout();
+ }
+ }
+ };
+ mHandler.postDelayed(mMaybeAbortPipEnterRunnable, PINNED_TASK_ABORT_TIMEOUT);
+ Slog.d(TAG, "a delayed check for potentially aborting PiP if "
+ + "in a wrong state is scheduled.");
+ }
+
+
/**
* Notifies when an activity enters or leaves PIP mode.
*
@@ -2403,14 +2466,6 @@
return false;
}
- return resumeFocusedTasksTopActivitiesUnchecked(targetRootTask, target, targetOptions,
- deferPause);
- }
-
- @VisibleForTesting
- boolean resumeFocusedTasksTopActivitiesUnchecked(
- Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,
- boolean deferPause) {
boolean result = false;
if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
|| getTopDisplayFocusedRootTask() == targetRootTask)) {
@@ -2900,6 +2955,14 @@
mService.mH.post(mDestroyAllActivitiesRunnable);
}
+ void removeAllMaybeAbortPipEnterRunnable() {
+ if (mMaybeAbortPipEnterRunnable == null) {
+ return;
+ }
+ mHandler.removeCallbacks(mMaybeAbortPipEnterRunnable);
+ mMaybeAbortPipEnterRunnable = null;
+ }
+
// Tries to put all activity tasks to sleep. Returns true if all tasks were
// successfully put to sleep.
boolean putTasksToSleep(boolean allowDelay, boolean shuttingDown) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 9d3ffa9..f23a440 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -4852,11 +4852,13 @@
/**
* Abort an incomplete pip-entry. If left in this state, it will cover everything but remain
* paused. If this is needed, there is a bug -- this should only be used for recovery.
+ *
+ * @return true if there is an inconsistency in the task and activity state.
*/
- void abortPipEnter(ActivityRecord top) {
+ boolean abortPipEnter(ActivityRecord top) {
// an incomplete state has the task PINNED but the activity not.
if (!inPinnedWindowingMode() || top.inPinnedWindowingMode() || !canMoveTaskToBack(this)) {
- return;
+ return false;
}
final Transition transition = new Transition(TRANSIT_TO_BACK, 0 /* flags */,
mTransitionController, mWmService.mSyncEngine);
@@ -4878,6 +4880,7 @@
top.setWindowingMode(WINDOWING_MODE_UNDEFINED);
top.mWaitForEnteringPinnedMode = false;
}
+ return true;
}
void resumeNextFocusAfterReparent() {
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 7a8bea0..2b631f7 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -2204,7 +2204,7 @@
static class ConfigOverrideHint {
@Nullable DisplayInfo mTmpOverrideDisplayInfo;
@Nullable ActivityRecord.CompatDisplayInsets mTmpCompatInsets;
- boolean mUseLegacyInsetsForStableBounds;
+ boolean mUseOverrideInsetsForStableBounds;
}
void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
@@ -2237,11 +2237,11 @@
@NonNull Configuration parentConfig, @Nullable ConfigOverrideHint overrideHint) {
DisplayInfo overrideDisplayInfo = null;
ActivityRecord.CompatDisplayInsets compatInsets = null;
- boolean useLegacyInsetsForStableBounds = false;
+ boolean useOverrideInsetsForStableBounds = false;
if (overrideHint != null) {
overrideDisplayInfo = overrideHint.mTmpOverrideDisplayInfo;
compatInsets = overrideHint.mTmpCompatInsets;
- useLegacyInsetsForStableBounds = overrideHint.mUseLegacyInsetsForStableBounds;
+ useOverrideInsetsForStableBounds = overrideHint.mUseOverrideInsetsForStableBounds;
if (overrideDisplayInfo != null) {
// Make sure the screen related configs can be computed by the provided
// display info.
@@ -2321,7 +2321,7 @@
// The non decor inset are areas that could never be removed in Honeycomb. See
// {@link WindowManagerPolicy#getNonDecorInsetsLw}.
calculateInsetFrames(mTmpNonDecorBounds, mTmpStableBounds, mTmpFullBounds, di,
- useLegacyInsetsForStableBounds);
+ useOverrideInsetsForStableBounds);
} else {
// Apply the given non-decor and stable insets to calculate the corresponding bounds
// for screen size of configuration.
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 664019a..1543263 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -1429,20 +1429,17 @@
}
}
if (mTransientLaunches != null) {
- InsetsControlTarget prevImeTarget = dc.getImeTarget(
- DisplayContent.IME_TARGET_CONTROL);
- InsetsControlTarget newImeTarget = null;
TaskDisplayArea transientTDA = null;
- // Transient-launch activities cannot be IME target (WindowState#canBeImeTarget),
- // so re-compute in case the IME target is changed after transition.
for (int t = 0; t < mTransientLaunches.size(); ++t) {
if (mTransientLaunches.keyAt(t).getDisplayContent() == dc) {
- newImeTarget = dc.computeImeTarget(true /* updateImeTarget */);
+ if (hasVisibleTransientLaunch) {
+ updateImeForVisibleTransientLaunch(dc);
+ }
transientTDA = mTransientLaunches.keyAt(i).getTaskDisplayArea();
break;
}
}
- if (mRecentsDisplayId != INVALID_DISPLAY && prevImeTarget == newImeTarget) {
+ if (!hasVisibleTransientLaunch && mRecentsDisplayId == dc.mDisplayId) {
// Restore IME icon only when moving the original app task to front from
// recents, in case IME icon may missing if the moving task has already been
// the current focused task.
@@ -1540,6 +1537,35 @@
return null;
}
+ /**
+ * Transient-launch activities cannot be IME target (see {@link WindowState#canBeImeTarget}),
+ * so re-compute in case the IME target is changed after transition.
+ */
+ private void updateImeForVisibleTransientLaunch(@NonNull DisplayContent dc) {
+ final WindowState imeTarget = dc.computeImeTarget(true /* updateImeTarget */);
+ final WindowState imeWindow = dc.mInputMethodWindow;
+ if (imeWindow == null || imeTarget == null
+ || !mController.hasCollectingRotationChange(dc, dc.getRotation())) {
+ return;
+ }
+ // Drop the insets leash if it is still controlled by previous (invisible) app. This avoids
+ // showing IME with old rotation on an app with new rotation if IME parent is updated
+ // but insets leash hasn't been refreshed, i.e. DisplayContent#updateImeParent is called
+ // but InsetsStateController#notifyControlTargetChanged still waits for IME to redraw.
+ final InsetsSourceProvider sourceProvider = imeWindow.getControllableInsetProvider();
+ if (sourceProvider == null || sourceProvider.mControl == null
+ || !sourceProvider.isClientVisible()
+ || imeTarget == sourceProvider.getControlTarget()) {
+ return;
+ }
+ final SurfaceControl imeInsetsLeash = sourceProvider.mControl.getLeash();
+ final InsetsControlTarget controlTarget = sourceProvider.getControlTarget();
+ if (imeInsetsLeash != null && controlTarget != null && controlTarget.getWindow() != null
+ && !controlTarget.getWindow().mToken.isVisible()) {
+ dc.getSyncTransaction().reparent(imeInsetsLeash, null);
+ }
+ }
+
void abort() {
// This calls back into itself via controller.abort, so just early return here.
if (mState == STATE_ABORT) return;
diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java
index 407b5d5..eeedec3 100644
--- a/services/core/java/com/android/server/wm/WindowManagerInternal.java
+++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java
@@ -1044,6 +1044,13 @@
int[] fromOrientations, int[] toOrientations);
/**
+ * Set current screen capture session id that will be used during sensitive content protections.
+ *
+ * @param sessionId Session id for this screen capture protection
+ */
+ public abstract void setBlockScreenCaptureForAppsSessionId(long sessionId);
+
+ /**
* Set whether screen capture should be disabled for all windows of a specific app windows based
* on sensitive content protections.
*
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 07e534c..de7c0eb 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -44,6 +44,7 @@
import static android.os.Process.myUid;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.permission.flags.Flags.sensitiveContentImprovements;
+import static android.permission.flags.Flags.sensitiveContentMetricsBugfix;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
@@ -113,6 +114,7 @@
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR;
import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.internal.util.FrameworkStatsLog.SENSITIVE_NOTIFICATION_APP_PROTECTION_APPLIED;
import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN;
import static com.android.server.LockGuard.INDEX_WINDOW;
import static com.android.server.LockGuard.installLock;
@@ -340,6 +342,7 @@
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastPrintWriter;
+import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.LatencyTracker;
import com.android.internal.view.WindowManagerPolicyThread;
import com.android.server.AnimationThread;
@@ -1110,6 +1113,9 @@
SystemPerformanceHinter mSystemPerformanceHinter;
@GuardedBy("mGlobalLock")
+ private long mSensitiveContentProtectionSessionId = 0;
+
+ @GuardedBy("mGlobalLock")
final SensitiveContentPackages mSensitiveContentPackages = new SensitiveContentPackages();
/**
* UIDs for which a Toast has been shown to indicate
@@ -4519,7 +4525,8 @@
}
}
- int getDisplayUserRotation(int displayId) {
+ @Override
+ public int getDisplayUserRotation(int displayId) {
synchronized (mGlobalLock) {
final DisplayContent display = mRoot.getDisplayContent(displayId);
if (display == null) {
@@ -8739,6 +8746,16 @@
}
@Override
+ public void setBlockScreenCaptureForAppsSessionId(long sessionId) {
+ synchronized (mGlobalLock) {
+ if (sensitiveContentMetricsBugfix()
+ && mSensitiveContentProtectionSessionId != sessionId) {
+ mSensitiveContentProtectionSessionId = sessionId;
+ }
+ }
+ }
+
+ @Override
public void addBlockScreenCaptureForApps(ArraySet<PackageInfo> packageInfos) {
synchronized (mGlobalLock) {
boolean modified =
@@ -10202,6 +10219,15 @@
Toast.LENGTH_SHORT)
.show();
});
+ // If blocked due to notification protection (null window token) log protection applied
+ if (sensitiveContentMetricsBugfix()
+ && mSensitiveContentPackages
+ .shouldBlockScreenCaptureForApp(w.getOwningPackage(), uid, null)) {
+ FrameworkStatsLog.write(
+ SENSITIVE_NOTIFICATION_APP_PROTECTION_APPLIED,
+ mSensitiveContentProtectionSessionId,
+ uid);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 909c1b3..1573d09 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -19,6 +19,7 @@
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.isStartResultSuccessful;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.TaskFragmentOperation.OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS;
@@ -69,7 +70,6 @@
import static com.android.server.wm.ActivityRecord.State.PAUSING;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission;
-import static com.android.server.wm.ActivityTaskManagerService.isPip2ExperimentEnabled;
import static com.android.server.wm.ActivityTaskSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK;
import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG;
@@ -838,8 +838,6 @@
}
private int applyTaskChanges(Task tr, WindowContainerTransaction.Change c) {
- final boolean wasPrevFocusableAndVisible = tr.isFocusableAndVisible();
-
int effects = applyChanges(tr, c);
final SurfaceControl.Transaction t = c.getBoundsChangeTransaction();
@@ -860,6 +858,17 @@
}
final int childWindowingMode = c.getActivityWindowingMode();
+ if (!ActivityTaskManagerService.isPip2ExperimentEnabled()
+ && tr.getWindowingMode() == WINDOWING_MODE_PINNED
+ && (childWindowingMode == WINDOWING_MODE_PINNED
+ || childWindowingMode == WINDOWING_MODE_UNDEFINED)) {
+ // If setActivityWindowingMode requested to match its pinned task's windowing mode,
+ // remove any inconsistency checking timeout callbacks for PiP.
+ Slog.d(TAG, "Task and activity windowing modes match, so remove any timeout "
+ + "abort PiP callbacks scheduled if needed; task_win_mode="
+ + tr.getWindowingMode() + ", activity_win_mode=" + childWindowingMode);
+ mService.mRootWindowContainer.removeAllMaybeAbortPipEnterRunnable();
+ }
if (childWindowingMode > -1) {
tr.forAllActivities(a -> { a.setWindowingMode(childWindowingMode); });
}
@@ -885,17 +894,8 @@
boolean canEnterPip = activity.checkEnterPictureInPictureState(
"applyTaskChanges", true /* beforeStopping */);
if (canEnterPip) {
- mService.mTaskSupervisor.beginDeferResume();
- try {
- canEnterPip = mService.mActivityClientController
- .requestPictureInPictureMode(activity);
- } finally {
- mService.mTaskSupervisor.endDeferResume();
- if (canEnterPip && !isPip2ExperimentEnabled()) {
- // Wait until the transaction is applied to only resume once.
- effects |= TRANSACT_EFFECTS_LIFECYCLE;
- }
- }
+ canEnterPip = mService.mActivityClientController
+ .requestPictureInPictureMode(activity);
}
if (!canEnterPip) {
// Restore the flag to its previous state when the activity cannot enter PIP.
@@ -904,11 +904,6 @@
}
}
- // Activity in this Task may resume/pause when enter/exit pip.
- if (wasPrevFocusableAndVisible != tr.isFocusableAndVisible()) {
- effects |= TRANSACT_EFFECTS_LIFECYCLE;
- }
-
return effects;
}
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 9d8246d..d91a211 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -631,6 +631,11 @@
return;
}
+ final WindowProcessController caller = mAtm.mProcessMap.getProcess(r.launchedFromPid);
+ if (caller != null && caller.mInstrumenting) {
+ return;
+ }
+
final long diff = launchTime - lastLaunchTime;
if (diff < RAPID_ACTIVITY_LAUNCH_MS) {
mRapidActivityLaunchCount++;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
index c4e2dc8..b76279b 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
@@ -32,7 +32,6 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
/**
* Implementation of {@link DevicePolicyCache}, to which {@link DevicePolicyManagerService} pushes
@@ -48,18 +47,11 @@
private final Object mLock = new Object();
/**
- * Indicates which user is screen capture disallowed on. Can be {@link UserHandle#USER_NULL},
- * {@link UserHandle#USER_ALL} or a concrete user ID.
- */
- @GuardedBy("mLock")
- private int mScreenCaptureDisallowedUser = UserHandle.USER_NULL;
-
- /**
* Indicates if screen capture is disallowed on a specific user or all users if
* it contains {@link UserHandle#USER_ALL}.
*/
@GuardedBy("mLock")
- private Set<Integer> mScreenCaptureDisallowedUsers = new HashSet<>();
+ private final Set<Integer> mScreenCaptureDisallowedUsers = new HashSet<>();
@GuardedBy("mLock")
private final SparseIntArray mPasswordQuality = new SparseIntArray();
@@ -70,9 +62,8 @@
@GuardedBy("mLock")
private ArrayMap<String, String> mLauncherShortcutOverrides = new ArrayMap<>();
-
/** Maps to {@code ActiveAdmin.mAdminCanGrantSensorsPermissions}. */
- private final AtomicBoolean mCanGrantSensorsPermissions = new AtomicBoolean(false);
+ private volatile boolean mCanGrantSensorsPermissions = false;
@GuardedBy("mLock")
private final SparseIntArray mContentProtectionPolicy = new SparseIntArray();
@@ -87,10 +78,6 @@
@Override
public boolean isScreenCaptureAllowed(int userHandle) {
- return isScreenCaptureAllowedInPolicyEngine(userHandle);
- }
-
- private boolean isScreenCaptureAllowedInPolicyEngine(int userHandle) {
// This won't work if resolution mechanism is not strictest applies, but it's ok for now.
synchronized (mLock) {
return !mScreenCaptureDisallowedUsers.contains(userHandle)
@@ -98,18 +85,6 @@
}
}
- public int getScreenCaptureDisallowedUser() {
- synchronized (mLock) {
- return mScreenCaptureDisallowedUser;
- }
- }
-
- public void setScreenCaptureDisallowedUser(int userHandle) {
- synchronized (mLock) {
- mScreenCaptureDisallowedUser = userHandle;
- }
- }
-
public void setScreenCaptureDisallowedUser(int userHandle, boolean disallowed) {
synchronized (mLock) {
if (disallowed) {
@@ -170,12 +145,12 @@
@Override
public boolean canAdminGrantSensorsPermissions() {
- return mCanGrantSensorsPermissions.get();
+ return mCanGrantSensorsPermissions;
}
/** Sets admin control over permission grants. */
public void setAdminCanGrantSensorsPermissions(boolean canGrant) {
- mCanGrantSensorsPermissions.set(canGrant);
+ mCanGrantSensorsPermissions = canGrant;
}
@Override
@@ -205,7 +180,7 @@
pw.println("Password quality: " + mPasswordQuality);
pw.println("Permission policy: " + mPermissionPolicy);
pw.println("Content protection policy: " + mContentProtectionPolicy);
- pw.println("Admin can grant sensors permission: " + mCanGrantSensorsPermissions.get());
+ pw.println("Admin can grant sensors permission: " + mCanGrantSensorsPermissions);
pw.print("Shortcuts overrides: ");
pw.println(mLauncherShortcutOverrides);
pw.decreaseIndent();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index be235b3b..6458eac 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -76,6 +76,7 @@
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SECURITY_LOGGING;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SMS;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_STATUS_BAR;
+import static android.Manifest.permission.MANAGE_DEVICE_POLICY_STORAGE_LIMIT;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SUPPORT_MESSAGE;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_DIALOGS;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_SYSTEM_UPDATES;
@@ -88,7 +89,6 @@
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WINDOWS;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIPE_DATA;
-import static android.Manifest.permission.MANAGE_DEVICE_POLICY_STORAGE_LIMIT;
import static android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS;
import static android.Manifest.permission.MASTER_CLEAR;
import static android.Manifest.permission.NOTIFY_PENDING_SYSTEM_UPDATE;
@@ -116,7 +116,6 @@
import static android.app.admin.DeviceAdminInfo.USES_POLICY_WIPE_DATA;
import static android.app.admin.DeviceAdminReceiver.ACTION_COMPLIANCE_ACKNOWLEDGEMENT_REQUIRED;
import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
-import static android.app.admin.DevicePolicyIdentifiers.AUTO_TIMEZONE_POLICY;
import static android.app.admin.DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_FINANCING_STATE_CHANGED;
import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED;
@@ -407,7 +406,6 @@
import android.location.Location;
import android.location.LocationManager;
import android.media.AudioManager;
-import android.media.IAudioService;
import android.net.ConnectivityManager;
import android.net.ConnectivitySettingsManager;
import android.net.IIpConnectivityMetrics;
@@ -1770,10 +1768,6 @@
ServiceManager.getService(Context.BACKUP_SERVICE));
}
- IAudioService getIAudioService() {
- return IAudioService.Stub.asInterface(ServiceManager.getService(Context.AUDIO_SERVICE));
- }
-
PersistentDataBlockManagerInternal getPersistentDataBlockManagerInternal() {
return LocalServices.getService(PersistentDataBlockManagerInternal.class);
}
@@ -1946,10 +1940,6 @@
name, value, userHandle);
}
- void settingsSecurePutInt(String name, int value) {
- Settings.Secure.putInt(mContext.getContentResolver(), name, value);
- }
-
int settingsGlobalGetInt(String name, int def) {
return Settings.Global.getInt(mContext.getContentResolver(), name, def);
}
@@ -1963,10 +1953,6 @@
Settings.Global.putInt(mContext.getContentResolver(), name, value);
}
- void settingsSecurePutString(String name, String value) {
- Settings.Secure.putString(mContext.getContentResolver(), name, value);
- }
-
void settingsGlobalPutString(String name, String value) {
Settings.Global.putString(mContext.getContentResolver(), name, value);
}
@@ -2907,16 +2893,6 @@
return poAdmin;
}
- @NonNull ActiveAdmin getOrganizationOwnedProfileOwnerLocked(final CallerIdentity caller) {
- Preconditions.checkCallAuthorization(
- mOwners.isProfileOwnerOfOrganizationOwnedDevice(caller.getUserId()),
- "Caller %s is not an admin of an org-owned device",
- caller.getComponentName());
- final ActiveAdmin profileOwner = getProfileOwnerLocked(caller.getUserId());
-
- return profileOwner;
- }
-
ActiveAdmin getProfileOwnerOrDeviceOwnerLocked(@UserIdInt int userId) {
ensureLocked();
// Try to find an admin which can use reqPolicy
@@ -2929,18 +2905,6 @@
return getDeviceOwnerLocked(userId);
}
- ActiveAdmin getProfileOwnerOrDefaultDeviceOwnerLocked(@UserIdInt int userId) {
- ensureLocked();
- // Try to find an admin which can use reqPolicy
- final ComponentName poAdminComponent = mOwners.getProfileOwnerComponent(userId);
-
- if (poAdminComponent != null) {
- return getProfileOwnerLocked(userId);
- }
-
- return getDefaultDeviceOwnerLocked(userId);
- }
-
@NonNull ActiveAdmin getParentOfAdminIfRequired(ActiveAdmin admin, boolean parent) {
Objects.requireNonNull(admin);
return parent ? admin.getParentActiveAdmin() : admin;
@@ -4453,25 +4417,6 @@
* <ul>
* <li>The active admins associated with the userHandle itself</li>
* <li>The parent active admins for each managed profile associated with the userHandle</li>
- * </ul>
- *
- * @param userHandle the affected user for whom to get the active admins
- * @return the list of active admins for the affected user
- */
- @GuardedBy("getLockObject()")
- private List<ActiveAdmin> getActiveAdminsForAffectedUserLocked(int userHandle) {
- if (isManagedProfile(userHandle)) {
- return getUserDataUnchecked(userHandle).mAdminList;
- }
- return getActiveAdminsForUserAndItsManagedProfilesLocked(userHandle,
- /* shouldIncludeProfileAdmins */ (user) -> false);
- }
-
- /**
- * Get the list of active admins for an affected user:
- * <ul>
- * <li>The active admins associated with the userHandle itself</li>
- * <li>The parent active admins for each managed profile associated with the userHandle</li>
* <li>The permission based admin associated with the userHandle itself</li>
* </ul>
*
@@ -8688,17 +8633,6 @@
.write();
}
- // Set the latest screen capture policy, overriding any existing ones.
- // userHandle can be one of USER_ALL, USER_NULL or a concrete userId.
- private void setScreenCaptureDisabled(int userHandle) {
- int current = mPolicyCache.getScreenCaptureDisallowedUser();
- if (userHandle == current) {
- return;
- }
- mPolicyCache.setScreenCaptureDisallowedUser(userHandle);
- updateScreenCaptureDisabled();
- }
-
/**
* Returns whether or not screen capture is disabled for any active admin.
*/
@@ -9915,16 +9849,6 @@
return doOrPo;
}
- ActiveAdmin getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceParentLocked(int userId) {
- ensureLocked();
- ActiveAdmin admin = getDeviceOwnerAdminLocked();
- if (admin != null) {
- return admin;
- }
- admin = getProfileOwnerOfOrganizationOwnedDeviceLocked(userId);
- return admin != null ? admin.getParentActiveAdmin() : null;
- }
-
@Override
public void clearDeviceOwner(String packageName) {
Objects.requireNonNull(packageName, "packageName is null");
@@ -10253,13 +10177,6 @@
return mInjector.hasUserSetupCompleted(getUserData(userHandle));
}
- private boolean hasPaired(int userHandle) {
- if (!mHasFeature) {
- return true;
- }
- return getUserData(userHandle).mPaired;
- }
-
@Override
public int getUserProvisioningState(int userHandle) {
if (!mHasFeature) {
@@ -11054,16 +10971,6 @@
return enforcingAdmin;
}
- private void enforceCanCallLockTaskLocked(CallerIdentity caller) {
- Preconditions.checkCallAuthorization(isProfileOwner(caller)
- || isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller));
-
- final int userId = caller.getUserId();
- if (!canDPCManagedUserUseLockTaskLocked(userId)) {
- throw new SecurityException("User " + userId + " is not allowed to use lock task");
- }
- }
-
private boolean isSystemUid(CallerIdentity caller) {
return UserHandle.isSameApp(caller.getUid(), Process.SYSTEM_UID);
}
@@ -12413,7 +12320,8 @@
if (Flags.headlessDeviceOwnerSingleUserEnabled()) {
// Block this method if the device is in headless main user mode
Preconditions.checkCallAuthorization(
- getHeadlessDeviceOwnerModeForDeviceOwner()
+ !mInjector.userManagerIsHeadlessSystemUserMode()
+ || getHeadlessDeviceOwnerModeForDeviceOwner()
!= HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER,
"createAndManageUser was called while in headless single user mode");
}
@@ -14595,15 +14503,6 @@
}
}
- private void setLockTaskPackagesLocked(int userHandle, List<String> packages) {
- DevicePolicyData policy = getUserData(userHandle);
- policy.mLockTaskPackages = packages;
-
- // Store the settings persistently.
- saveSettingsLocked(userHandle);
- updateLockTaskPackagesLocked(mContext, packages, userHandle);
- }
-
@Override
public String[] getLockTaskPackages(ComponentName who, String callerPackageName) {
CallerIdentity caller = getCallerIdentity(who, callerPackageName);
@@ -14653,7 +14552,6 @@
"Cannot use LOCK_TASK_FEATURE_NOTIFICATIONS without LOCK_TASK_FEATURE_HOME");
CallerIdentity caller = getCallerIdentity(who, callerPackageName);
- final int userHandle = caller.getUserId();
synchronized (getLockObject()) {
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOCK_TASK_FEATURES);
}
@@ -14689,13 +14587,6 @@
}
}
- private void setLockTaskFeaturesLocked(int userHandle, int flags) {
- DevicePolicyData policy = getUserData(userHandle);
- policy.mLockTaskFeatures = flags;
- saveSettingsLocked(userHandle);
- updateLockTaskFeaturesLocked(flags, userHandle);
- }
-
@Override
public int getLockTaskFeatures(ComponentName who, String callerPackageName) {
CallerIdentity caller = getCallerIdentity(who, callerPackageName);
@@ -16171,29 +16062,6 @@
}
}
-
- /**
- * Excludes restrictions imposed by UserManager.
- */
- private List<UserManager.EnforcingUser> getDevicePolicySources(
- List<UserManager.EnforcingUser> sources) {
- int sizeBefore = sources.size();
- List<UserManager.EnforcingUser> realSources = new ArrayList<>(sizeBefore);
- for (int i = 0; i < sizeBefore; i++) {
- UserManager.EnforcingUser source = sources.get(i);
- int type = source.getUserRestrictionSource();
- if (type != UserManager.RESTRICTION_SOURCE_PROFILE_OWNER
- && type != UserManager.RESTRICTION_SOURCE_DEVICE_OWNER) {
- // TODO(b/128928355): add unit test
- Slogf.d(LOG_TAG, "excluding source of type %s at index %d",
- userRestrictionSourceToString(type), i);
- continue;
- }
- realSources.add(source);
- }
- return realSources;
- }
-
private static String userRestrictionSourceToString(@UserRestrictionSource int source) {
return DebugUtils.flagsToString(UserManager.class, "RESTRICTION_", source);
}
@@ -20870,17 +20738,6 @@
}
}
- private void suspendPersonalAppsInPackageManager(int userId) {
- mInjector.binderWithCleanCallingIdentity(() -> {
- final String[] appsToSuspend = mInjector.getPersonalAppsForSuspension(userId);
- final String[] failedApps = mInjector.getPackageManagerInternal()
- .setPackagesSuspendedByAdmin(userId, appsToSuspend, true);
- if (!ArrayUtils.isEmpty(failedApps)) {
- Slogf.wtf(LOG_TAG, "Failed to suspend apps: " + String.join(",", failedApps));
- }
- });
- }
-
private void notifyIfManagedSubscriptionsAreUnavailable(
UserHandle managedProfile, boolean managedProfileAvailable) {
if (!isManagedProfile(managedProfile.getIdentifier())) {
@@ -23329,14 +23186,6 @@
return getEnforcingAdminForCaller(admin, callerPackageName);
}
- private static final HashMap<String, String> POLICY_IDENTIFIER_TO_PERMISSION = new HashMap<>();
- {
- POLICY_IDENTIFIER_TO_PERMISSION.put(AUTO_TIMEZONE_POLICY, SET_TIME_ZONE);
- }
-
- private static final HashMap<String, Integer> POLICY_IDENTIFIER_TO_ACTIVE_ADMIN_POLICY =
- new HashMap<>();
-
/**
* Checks if the calling process has been granted permission to apply a device policy.
*
@@ -23355,7 +23204,6 @@
}
}
-
/**
* Checks if the calling process has been granted permission to apply a device policy on a
* specific user. Only one permission provided in the list needs to be granted to pass this
@@ -23472,10 +23320,12 @@
}
private boolean hasAdminPolicy(int adminPolicy, String callerPackageName) {
- CallerIdentity caller = getCallerIdentity(callerPackageName);
- ActiveAdmin deviceAdmin = getActiveAdminWithPolicyForUidLocked(
- null, adminPolicy, caller.getUid());
- return deviceAdmin != null;
+ synchronized (getLockObject()) {
+ CallerIdentity caller = getCallerIdentity(callerPackageName);
+ ActiveAdmin deviceAdmin = getActiveAdminWithPolicyForUidLocked(
+ null, adminPolicy, caller.getUid());
+ return deviceAdmin != null;
+ }
}
/**
@@ -24455,52 +24305,6 @@
}
}
- // We need to add a mapping of policyId to permission in POLICY_IDENTIFIER_TO_PERMISSION
- // for each migrated permission.
- private List<ActiveAdmin> getNonDPCActiveAdminsForPolicyLocked(String policyIdentifier) {
- Integer activeAdminPolicy = POLICY_IDENTIFIER_TO_ACTIVE_ADMIN_POLICY.get(policyIdentifier);
- if (activeAdminPolicy == null) {
- Slogf.e(LOG_TAG,
- "Can't find a active admin policy for %s in POLICY_IDENTIFIER_TO_PERMISSION",
- policyIdentifier);
- return new ArrayList<>();
- }
-
- List<ActiveAdmin> admins = new ArrayList<>();
- for (UserInfo userInfo : mUserManager.getUsers()) {
- List<ComponentName> activeAdmins = getActiveAdmins(userInfo.id);
- for (ComponentName admin : activeAdmins) {
- if (isDeviceOwner(admin, userInfo.id) || isProfileOwner(admin, userInfo.id)) {
- continue;
- }
- DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
- if (isActiveAdminWithPolicyForUserLocked(
- policy.mAdminMap.get(admin), activeAdminPolicy,
- userInfo.id)) {
- admins.add(policy.mAdminMap.get(admin));
- }
- }
- }
- return admins;
- }
-
- // TODO: this can actually accept an EnforcingAdmin that gets created in the permission
- // check method.
- private boolean isCallerActiveAdminOrDelegate(
- CallerIdentity caller, @Nullable String delegateScope) {
- return mInjector.binderWithCleanCallingIdentity(() -> {
- List<ComponentName> activeAdmins = getActiveAdmins(caller.getUserId());
- if (activeAdmins != null) {
- for (ComponentName admin : activeAdmins) {
- if (admin.getPackageName().equals(caller.getPackageName())) {
- return true;
- }
- }
- }
- return delegateScope != null && isCallerDelegate(caller, delegateScope);
- });
- }
-
private ActiveAdmin getActiveAdminForCaller(@Nullable ComponentName who,
CallerIdentity caller) {
synchronized (getLockObject()) {
diff --git a/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleStateTransitions.java b/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleStateTransitions.java
index 16daacb..aa7532a 100644
--- a/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleStateTransitions.java
+++ b/services/foldables/devicestateprovider/src/com/android/server/policy/BookStyleStateTransitions.java
@@ -412,7 +412,7 @@
/* stickyKeepInnerUntil45Degrees */ true,
PreferredScreen.INNER,
/* setStickyKeepOuterUntil90Degrees */ null,
- /* setStickyKeepInnerUntil45Degrees */ false
+ /* setStickyKeepInnerUntil45Degrees */ null
));
DEFAULT_STATE_TRANSITIONS.add(new StateTransition(
HingeAngle.ANGLE_45_TO_90,
@@ -492,7 +492,7 @@
/* stickyKeepInnerUntil45Degrees */ true,
PreferredScreen.INNER,
/* setStickyKeepOuterUntil90Degrees */ null,
- /* setStickyKeepInnerUntil45Degrees */ false
+ /* setStickyKeepInnerUntil45Degrees */ null
));
DEFAULT_STATE_TRANSITIONS.add(new StateTransition(
HingeAngle.ANGLE_45_TO_90,
diff --git a/services/foldables/devicestateprovider/tests/src/com/android/server/policy/BookStyleDeviceStatePolicyTest.java b/services/foldables/devicestateprovider/tests/src/com/android/server/policy/BookStyleDeviceStatePolicyTest.java
index 9f07aa8..2d725d1 100644
--- a/services/foldables/devicestateprovider/tests/src/com/android/server/policy/BookStyleDeviceStatePolicyTest.java
+++ b/services/foldables/devicestateprovider/tests/src/com/android/server/policy/BookStyleDeviceStatePolicyTest.java
@@ -511,7 +511,7 @@
}
@Test
- public void test_unfoldTo60Degrees_andFoldTo10_switchesToClosedState() {
+ public void test_unfoldTo60Degrees_andFoldTo10_doesNotSwitchToClosedState() {
sendHingeAngle(0f);
sendRightSideFlatSensorEvent(false);
mProvider.setListener(mListener);
@@ -522,6 +522,36 @@
sendHingeAngle(10f);
+ verify(mListener, never()).onStateChanged(anyInt());
+ }
+
+ @Test
+ public void test_unfoldTo100Degrees_andFoldTo10_switchesToClosedState() {
+ sendHingeAngle(0f);
+ sendRightSideFlatSensorEvent(false);
+ mProvider.setListener(mListener);
+ assertLatestReportedState(DEVICE_STATE_CLOSED);
+ sendHingeAngle(100f);
+ assertLatestReportedState(DEVICE_STATE_HALF_OPENED);
+ clearInvocations(mListener);
+
+ sendHingeAngle(10f);
+
+ verify(mListener).onStateChanged(DEVICE_STATE_CLOSED);
+ }
+
+ @Test
+ public void test_unfoldTo10Degrees_andFoldTo0_switchesToClosedState() {
+ sendHingeAngle(0f);
+ sendRightSideFlatSensorEvent(false);
+ mProvider.setListener(mListener);
+ assertLatestReportedState(DEVICE_STATE_CLOSED);
+ sendHingeAngle(10f);
+ assertLatestReportedState(DEVICE_STATE_HALF_OPENED);
+ clearInvocations(mListener);
+
+ sendHingeAngle(0f);
+
verify(mListener).onStateChanged(DEVICE_STATE_CLOSED);
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 648b810..8caf5ae 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -91,6 +91,7 @@
import android.util.Dumpable;
import android.util.EventLog;
import android.util.IndentingPrintWriter;
+import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.TimeUtils;
@@ -2005,9 +2006,11 @@
mSystemServiceManager.startService(new FontManagerService.Lifecycle(context, safeMode));
t.traceEnd();
- t.traceBegin("StartTextServicesManager");
- mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class);
- t.traceEnd();
+ if (!isWatch || !android.server.Flags.removeTextService()) {
+ t.traceBegin("StartTextServicesManager");
+ mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class);
+ t.traceEnd();
+ }
if (!disableSystemTextClassifier) {
t.traceBegin("StartTextClassificationManagerService");
diff --git a/services/java/com/android/server/flags.aconfig b/services/java/com/android/server/flags.aconfig
index 854bc0f..38354e8 100644
--- a/services/java/com/android/server/flags.aconfig
+++ b/services/java/com/android/server/flags.aconfig
@@ -8,3 +8,10 @@
is_fixed_read_only: true
bug: "324153471"
}
+
+flag {
+ name: "remove_text_service"
+ namespace: "wear_frameworks"
+ description: "Remove TextServiceManagerService on Wear"
+ bug: "323720705"
+}
\ No newline at end of file
diff --git a/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt b/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
index c0d988d..b0c7073 100644
--- a/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
+++ b/services/permission/java/com/android/server/permission/access/appop/AppOpService.kt
@@ -20,6 +20,7 @@
import android.companion.virtual.VirtualDeviceManager
import android.os.Handler
import android.os.UserHandle
+import android.permission.PermissionManager
import android.permission.flags.Flags
import android.util.ArrayMap
import android.util.ArraySet
@@ -142,7 +143,7 @@
}
}
- override fun getNonDefaultUidModes(uid: Int, persistentDeviceId: String): SparseIntArray {
+ override fun getNonDefaultUidModes(uid: Int, deviceId: String): SparseIntArray {
val appId = UserHandle.getAppId(uid)
val userId = UserHandle.getUserId(uid)
service.getState {
@@ -150,7 +151,8 @@
with(appIdPolicy) { opNameMapToOpSparseArray(getAppOpModes(appId, userId)?.map) }
if (Flags.runtimePermissionAppopsMappingEnabled()) {
runtimePermissionNameToAppOp.forEachIndexed { _, permissionName, appOpCode ->
- val mode = getUidModeFromPermissionState(appId, userId, permissionName)
+ val mode =
+ getUidModeFromPermissionState(appId, userId, permissionName, deviceId)
if (mode != AppOpsManager.opToDefaultMode(appOpCode)) {
modes[appOpCode] = mode
}
@@ -165,7 +167,7 @@
return opNameMapToOpSparseArray(getPackageModes(packageName, userId))
}
- override fun getUidMode(uid: Int, persistentDeviceId: String, op: Int): Int {
+ override fun getUidMode(uid: Int, deviceId: String, op: Int): Int {
val appId = UserHandle.getAppId(uid)
val userId = UserHandle.getUserId(uid)
val opName = AppOpsManager.opToPublicName(op)
@@ -174,7 +176,9 @@
return if (!Flags.runtimePermissionAppopsMappingEnabled() || permissionName == null) {
service.getState { with(appIdPolicy) { getAppOpMode(appId, userId, opName) } }
} else {
- service.getState { getUidModeFromPermissionState(appId, userId, permissionName) }
+ service.getState {
+ getUidModeFromPermissionState(appId, userId, permissionName, deviceId)
+ }
}
}
@@ -187,15 +191,31 @@
private fun GetStateScope.getUidModeFromPermissionState(
appId: Int,
userId: Int,
- permissionName: String
+ permissionName: String,
+ deviceId: String
): Int {
+ val checkDevicePermissionFlags =
+ deviceId != VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT &&
+ permissionName in PermissionManager.DEVICE_AWARE_PERMISSIONS
val permissionFlags =
- with(permissionPolicy) { getPermissionFlags(appId, userId, permissionName) }
+ if (checkDevicePermissionFlags) {
+ with(devicePermissionPolicy) {
+ getPermissionFlags(appId, deviceId, userId, permissionName)
+ }
+ } else {
+ with(permissionPolicy) { getPermissionFlags(appId, userId, permissionName) }
+ }
val backgroundPermissionName = foregroundToBackgroundPermissionName[permissionName]
val backgroundPermissionFlags =
if (backgroundPermissionName != null) {
- with(permissionPolicy) {
- getPermissionFlags(appId, userId, backgroundPermissionName)
+ if (checkDevicePermissionFlags) {
+ with(devicePermissionPolicy) {
+ getPermissionFlags(appId, deviceId, userId, backgroundPermissionName)
+ }
+ } else {
+ with(permissionPolicy) {
+ getPermissionFlags(appId, userId, backgroundPermissionName)
+ }
}
} else {
PermissionFlags.RUNTIME_GRANTED
@@ -207,7 +227,7 @@
val fullerPermissionName =
PermissionService.getFullerPermission(permissionName) ?: return result
- return getUidModeFromPermissionState(appId, userId, fullerPermissionName)
+ return getUidModeFromPermissionState(appId, userId, fullerPermissionName, deviceId)
}
private fun evaluateModeFromPermissionFlags(
@@ -224,7 +244,7 @@
MODE_IGNORED
}
- override fun setUidMode(uid: Int, persistentDeviceId: String, code: Int, mode: Int): Boolean {
+ override fun setUidMode(uid: Int, deviceId: String, code: Int, mode: Int): Boolean {
if (
Flags.runtimePermissionAppopsMappingEnabled() && code in runtimeAppOpToPermissionNames
) {
@@ -308,7 +328,7 @@
// and we have our own persistence.
}
- override fun getForegroundOps(uid: Int, persistentDeviceId: String): SparseBooleanArray {
+ override fun getForegroundOps(uid: Int, deviceId: String): SparseBooleanArray {
return SparseBooleanArray().apply {
getUidModes(uid)?.forEachIndexed { _, op, mode ->
if (mode == AppOpsManager.MODE_FOREGROUND) {
@@ -317,7 +337,7 @@
}
if (Flags.runtimePermissionAppopsMappingEnabled()) {
foregroundableOps.forEachIndexed { _, op, _ ->
- if (getUidMode(uid, persistentDeviceId, op) == AppOpsManager.MODE_FOREGROUND) {
+ if (getUidMode(uid, deviceId, op) == AppOpsManager.MODE_FOREGROUND) {
this[op] = true
}
}
@@ -501,7 +521,7 @@
)
}
}
- ?: runtimePermissionNameToAppOp[permissionName]?.let { appOpCode ->
+ ?: runtimePermissionNameToAppOp[permissionName]?.let { appOpCode ->
addPendingChangedModeIfNeeded(
appId,
userId,
diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
index 2134278..1535298 100644
--- a/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
+++ b/services/tests/InputMethodSystemServerTests/src/com/android/inputmethodservice/InputMethodServiceTest.java
@@ -38,7 +38,6 @@
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.util.Log;
-import android.view.KeyEvent;
import android.view.WindowManagerGlobal;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
@@ -601,28 +600,6 @@
false /* orientationPortrait */);
}
- @Test
- public void switchesKeyboardLayout_withShortcut_onlyIfImeVisible() throws Exception {
- setShowImeWithHardKeyboard(true /* enabled */);
-
- assertThat(mInputMethodService.isInputViewShown()).isFalse();
- assertThat(mInputMethodService.onKeyDown(KeyEvent.KEYCODE_SPACE,
- new KeyEvent(0 /* downTime */, 0 /* eventTime */, KeyEvent.ACTION_DOWN,
- KeyEvent.KEYCODE_SPACE, 0 /* repeat */,
- KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON))).isFalse();
-
- verifyInputViewStatusOnMainSync(
- () -> assertThat(mActivity.showImeWithInputMethodManager(0 /* flags */)).isTrue(),
- true /* expected */,
- true /* inputViewStarted */);
-
- assertThat(mInputMethodService.isInputViewShown()).isTrue();
- assertThat(mInputMethodService.onKeyDown(KeyEvent.KEYCODE_SPACE,
- new KeyEvent(0 /* downTime */, 0 /* eventTime */, KeyEvent.ACTION_DOWN,
- KeyEvent.KEYCODE_SPACE, 0 /* repeat */,
- KeyEvent.META_CTRL_LEFT_ON | KeyEvent.META_CTRL_ON))).isTrue();
- }
-
/**
* This checks that when the system navigation bar is not created (e.g. emulator),
* then the IME caption bar is also not created.
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayBrightnessStateTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayBrightnessStateTest.java
index 6d89e80..8db896b 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayBrightnessStateTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayBrightnessStateTest.java
@@ -47,6 +47,7 @@
float sdrBrightness = 0.2f;
boolean shouldUseAutoBrightness = true;
boolean shouldUpdateScreenBrightnessSetting = true;
+ int brightnessAdjustmentFlag = 2;
BrightnessReason brightnessReason = new BrightnessReason();
brightnessReason.setReason(BrightnessReason.REASON_AUTOMATIC);
brightnessReason.setModifier(BrightnessReason.MODIFIER_DIMMED);
@@ -56,6 +57,7 @@
.setBrightnessReason(brightnessReason)
.setShouldUseAutoBrightness(shouldUseAutoBrightness)
.setShouldUpdateScreenBrightnessSetting(shouldUpdateScreenBrightnessSetting)
+ .setBrightnessAdjustmentFlag(brightnessAdjustmentFlag)
.build();
assertEquals(displayBrightnessState.getBrightness(), brightness, FLOAT_DELTA);
@@ -105,7 +107,9 @@
.append("\n shouldUpdateScreenBrightnessSetting:")
.append(displayBrightnessState.shouldUpdateScreenBrightnessSetting())
.append("\n mBrightnessEvent:")
- .append(Objects.toString(displayBrightnessState.getBrightnessEvent(), "null"));
+ .append(Objects.toString(displayBrightnessState.getBrightnessEvent(), "null"))
+ .append("\n mBrightnessAdjustmentFlag:")
+ .append(displayBrightnessState.getBrightnessAdjustmentFlag());
return sb.toString();
}
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
index de93914..78ebdb1 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -1312,7 +1312,7 @@
when(mHolder.hbmController.getHighBrightnessMode()).thenReturn(
BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR);
when(mHolder.hbmController.getHdrBrightnessValue()).thenReturn(PowerManager.BRIGHTNESS_MAX);
- when(mHolder.hdrClamper.getMaxBrightness()).thenReturn(clampedBrightness);
+ when(mHolder.hdrClamper.clamp(PowerManager.BRIGHTNESS_MAX)).thenReturn(clampedBrightness);
when(mHolder.hdrClamper.getTransitionRate()).thenReturn(transitionRate);
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
index 1ae4099..13a1445 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
@@ -20,6 +20,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -113,7 +114,8 @@
when(mDisplayBrightnessStrategySelector.selectStrategy(
any(StrategySelectionRequest.class))).thenReturn(displayBrightnessStrategy);
mDisplayBrightnessController.updateBrightness(displayPowerRequest, targetDisplayState);
- verify(displayBrightnessStrategy).updateBrightness(displayPowerRequest);
+ verify(displayBrightnessStrategy).updateBrightness(
+ eq(new StrategyExecutionRequest(displayPowerRequest, DEFAULT_BRIGHTNESS)));
assertEquals(mDisplayBrightnessController.getCurrentDisplayBrightnessStrategy(),
displayBrightnessStrategy);
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java
index 39ffe5b..c785ea6 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/clamper/HdrClamperTest.java
@@ -221,6 +221,18 @@
assertEquals(0.04f, mHdrClamper.getTransitionRate(), FLOAT_TOLERANCE);
}
+ @Test
+ public void testCalmper_transitionRateOverriddenByOtherRequest() {
+ mHdrClamper.onAmbientLuxChange(499);
+
+ mClock.fastForward(3000);
+ mTestHandler.timeAdvance();
+ assertEquals(0.6f, mHdrClamper.getMaxBrightness(), FLOAT_TOLERANCE);
+ assertEquals(0.04, mHdrClamper.getTransitionRate(), FLOAT_TOLERANCE);
+ // getTransitionRate should reset transitionRate
+ assertEquals(-1f, mHdrClamper.getTransitionRate(), FLOAT_TOLERANCE);
+ }
+
// MsgInfo.sendTime is calculated first by adding SystemClock.uptimeMillis()
// (in Handler.sendMessageDelayed) and then by subtracting SystemClock.uptimeMillis()
// (in TestHandler.sendMessageAtTime, there might be several milliseconds difference between
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java
index 6e163ca..54f2268 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/AutomaticBrightnessStrategyTest.java
@@ -41,8 +41,10 @@
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;
import com.android.server.display.AutomaticBrightnessController;
+import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import org.junit.After;
import org.junit.Before;
@@ -295,15 +297,11 @@
mContext.getContentResolver(),
Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
UserHandle.USER_CURRENT), 0.0f);
- assertEquals(BrightnessReason.ADJUSTMENT_AUTO,
- mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentReasonsFlags());
float invalidBrightness = -0.5f;
mAutomaticBrightnessStrategy
.adjustAutomaticBrightnessStateIfValid(invalidBrightness);
assertEquals(autoBrightnessAdjustment,
mAutomaticBrightnessStrategy.getAutoBrightnessAdjustment(), 0.0f);
- assertEquals(0,
- mAutomaticBrightnessStrategy.getAutoBrightnessAdjustmentReasonsFlags());
}
@Test
@@ -426,6 +424,80 @@
assertTrue(mAutomaticBrightnessStrategy.isAutoBrightnessValid());
}
+ @Test
+ public void
+ updateBrightness_constructsDisplayBrightnessState_withAdjustmentAutoAdjustmentFlag() {
+ BrightnessEvent brightnessEvent = new BrightnessEvent(DISPLAY_ID);
+ mAutomaticBrightnessStrategy = new AutomaticBrightnessStrategy(
+ mContext, DISPLAY_ID, displayId -> brightnessEvent);
+ new AutomaticBrightnessStrategy(mContext, DISPLAY_ID);
+ mAutomaticBrightnessStrategy.setAutomaticBrightnessController(
+ mAutomaticBrightnessController);
+ float brightness = 0.4f;
+ BrightnessReason brightnessReason = new BrightnessReason();
+ brightnessReason.setReason(BrightnessReason.REASON_AUTOMATIC);
+ when(mAutomaticBrightnessController.getAutomaticScreenBrightness(brightnessEvent))
+ .thenReturn(brightness);
+
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest =
+ mock(DisplayManagerInternal.DisplayPowerRequest.class);
+ DisplayBrightnessState expectedDisplayBrightnessState = new DisplayBrightnessState.Builder()
+ .setBrightness(brightness)
+ .setSdrBrightness(brightness)
+ .setBrightnessReason(brightnessReason)
+ .setDisplayBrightnessStrategyName(mAutomaticBrightnessStrategy.getName())
+ .setIsSlowChange(false)
+ .setBrightnessEvent(brightnessEvent)
+ .setBrightnessAdjustmentFlag(BrightnessReason.ADJUSTMENT_AUTO)
+ .setShouldUpdateScreenBrightnessSetting(true)
+ .build();
+ DisplayBrightnessState actualDisplayBrightnessState = mAutomaticBrightnessStrategy
+ .updateBrightness(new StrategyExecutionRequest(displayPowerRequest, 0.6f));
+ assertEquals(expectedDisplayBrightnessState, actualDisplayBrightnessState);
+ }
+
+ @Test
+ public void
+ updateBrightness_constructsDisplayBrightnessState_withAdjustmentTempAdjustmentFlag() {
+ BrightnessEvent brightnessEvent = new BrightnessEvent(DISPLAY_ID);
+ mAutomaticBrightnessStrategy = new AutomaticBrightnessStrategy(
+ mContext, DISPLAY_ID, displayId -> brightnessEvent);
+ new AutomaticBrightnessStrategy(mContext, DISPLAY_ID);
+ mAutomaticBrightnessStrategy.setAutomaticBrightnessController(
+ mAutomaticBrightnessController);
+ float brightness = 0.4f;
+ BrightnessReason brightnessReason = new BrightnessReason();
+ brightnessReason.setReason(BrightnessReason.REASON_AUTOMATIC);
+ when(mAutomaticBrightnessController.getAutomaticScreenBrightness(brightnessEvent))
+ .thenReturn(brightness);
+
+ DisplayManagerInternal.DisplayPowerRequest displayPowerRequest =
+ mock(DisplayManagerInternal.DisplayPowerRequest.class);
+ float temporaryBrightness = 0.3f;
+ float autoBrightnessAdjustment = 0.1f;
+ mAutomaticBrightnessStrategy.setTemporaryAutoBrightnessAdjustment(temporaryBrightness);
+ mAutomaticBrightnessStrategy.accommodateUserBrightnessChanges(true,
+ brightness, DisplayManagerInternal.DisplayPowerRequest.POLICY_BRIGHT,
+ Display.STATE_ON, mock(BrightnessConfiguration.class),
+ AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED);
+ when(mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment()).thenReturn(
+ autoBrightnessAdjustment);
+
+ DisplayBrightnessState expectedDisplayBrightnessState = new DisplayBrightnessState.Builder()
+ .setBrightness(brightness)
+ .setSdrBrightness(brightness)
+ .setBrightnessReason(brightnessReason)
+ .setDisplayBrightnessStrategyName(mAutomaticBrightnessStrategy.getName())
+ .setIsSlowChange(false)
+ .setBrightnessEvent(brightnessEvent)
+ .setBrightnessAdjustmentFlag(BrightnessReason.ADJUSTMENT_AUTO_TEMP)
+ .setShouldUpdateScreenBrightnessSetting(true)
+ .build();
+ DisplayBrightnessState actualDisplayBrightnessState = mAutomaticBrightnessStrategy
+ .updateBrightness(new StrategyExecutionRequest(displayPowerRequest, 0.6f));
+ assertEquals(expectedDisplayBrightnessState, actualDisplayBrightnessState);
+ }
+
private void setPendingAutoBrightnessAdjustment(float pendingAutoBrightnessAdjustment) {
Settings.System.putFloat(mContext.getContentResolver(),
Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, pendingAutoBrightnessAdjustment);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/BoostBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/BoostBrightnessStrategyTest.java
index c434631..47f1746 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/BoostBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/BoostBrightnessStrategyTest.java
@@ -27,6 +27,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import org.junit.Before;
import org.junit.Test;
@@ -58,7 +59,8 @@
.setDisplayBrightnessStrategyName(mBoostBrightnessStrategy.getName())
.build();
DisplayBrightnessState updatedDisplayBrightnessState =
- mBoostBrightnessStrategy.updateBrightness(displayPowerRequest);
+ mBoostBrightnessStrategy.updateBrightness(
+ new StrategyExecutionRequest(displayPowerRequest, 0.2f));
assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/DozeBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/DozeBrightnessStrategyTest.java
index d60caf6..9246780 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/DozeBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/DozeBrightnessStrategyTest.java
@@ -25,6 +25,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import org.junit.Before;
import org.junit.Test;
@@ -55,7 +56,8 @@
.setDisplayBrightnessStrategyName(mDozeBrightnessModeStrategy.getName())
.build();
DisplayBrightnessState updatedDisplayBrightnessState =
- mDozeBrightnessModeStrategy.updateBrightness(displayPowerRequest);
+ mDozeBrightnessModeStrategy.updateBrightness(
+ new StrategyExecutionRequest(displayPowerRequest, 0.2f));
assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
}
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/FollowerBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/FollowerBrightnessStrategyTest.java
index d8569f7..682c9cc 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/FollowerBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/FollowerBrightnessStrategyTest.java
@@ -26,6 +26,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import org.junit.Before;
import org.junit.Test;
@@ -59,7 +60,8 @@
.setIsSlowChange(slowChange)
.build();
DisplayBrightnessState updatedDisplayBrightnessState =
- mFollowerBrightnessStrategy.updateBrightness(displayPowerRequest);
+ mFollowerBrightnessStrategy.updateBrightness(
+ new StrategyExecutionRequest(displayPowerRequest, 0.2f));
assertEquals(expectedDisplayBrightnessState, updatedDisplayBrightnessState);
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OffloadBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OffloadBrightnessStrategyTest.java
index c2fa4eb..ccf6309 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OffloadBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OffloadBrightnessStrategyTest.java
@@ -28,6 +28,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import com.android.server.display.brightness.StrategySelectionNotifyRequest;
import com.android.server.display.feature.DisplayManagerFlags;
@@ -70,7 +71,8 @@
.setShouldUpdateScreenBrightnessSetting(true)
.build();
DisplayBrightnessState updatedDisplayBrightnessState =
- mOffloadBrightnessStrategy.updateBrightness(displayPowerRequest);
+ mOffloadBrightnessStrategy.updateBrightness(
+ new StrategyExecutionRequest(displayPowerRequest, 0.2f));
assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
assertEquals(PowerManager.BRIGHTNESS_INVALID_FLOAT, mOffloadBrightnessStrategy
.getOffloadScreenBrightness(), 0.0f);
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OverrideBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OverrideBrightnessStrategyTest.java
index 530245d..8e7b463 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OverrideBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/OverrideBrightnessStrategyTest.java
@@ -26,6 +26,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import org.junit.Before;
import org.junit.Test;
@@ -58,7 +59,8 @@
.setDisplayBrightnessStrategyName(mOverrideBrightnessStrategy.getName())
.build();
DisplayBrightnessState updatedDisplayBrightnessState =
- mOverrideBrightnessStrategy.updateBrightness(displayPowerRequest);
+ mOverrideBrightnessStrategy.updateBrightness(
+ new StrategyExecutionRequest(displayPowerRequest, 0.2f));
assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategyTest.java
index 7147aa8..e799d0e 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/ScreenOffBrightnessStrategyTest.java
@@ -26,6 +26,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import org.junit.Before;
import org.junit.Test;
@@ -56,7 +57,8 @@
.getName())
.build();
DisplayBrightnessState updatedDisplayBrightnessState =
- mScreenOffBrightnessModeStrategy.updateBrightness(displayPowerRequest);
+ mScreenOffBrightnessModeStrategy.updateBrightness(
+ new StrategyExecutionRequest(displayPowerRequest, 0.2f));
assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
}
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategyTest.java b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategyTest.java
index 9830edb..aaada41 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategyTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/brightness/strategy/TemporaryBrightnessStrategyTest.java
@@ -26,6 +26,7 @@
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.brightness.BrightnessReason;
+import com.android.server.display.brightness.StrategyExecutionRequest;
import org.junit.Before;
import org.junit.Test;
@@ -58,7 +59,8 @@
.setDisplayBrightnessStrategyName(mTemporaryBrightnessStrategy.getName())
.build();
DisplayBrightnessState updatedDisplayBrightnessState =
- mTemporaryBrightnessStrategy.updateBrightness(displayPowerRequest);
+ mTemporaryBrightnessStrategy.updateBrightness(
+ new StrategyExecutionRequest(displayPowerRequest, 0.2f));
assertEquals(updatedDisplayBrightnessState, expectedDisplayBrightnessState);
}
diff --git a/services/tests/dreamservicetests/src/com/android/server/dreams/DreamAccessibilityTest.java b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamAccessibilityTest.java
new file mode 100644
index 0000000..99968d5
--- /dev/null
+++ b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamAccessibilityTest.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2024 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.dreams;
+
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.service.dreams.utils.DreamAccessibility;
+import android.text.TextUtils;
+import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DreamAccessibilityTest {
+
+ @Mock
+ private View mView;
+
+ @Mock
+ private Context mContext;
+
+ @Mock
+ private Resources mResources;
+
+ @Mock
+ private AccessibilityNodeInfo mAccessibilityNodeInfo;
+
+ @Captor
+ private ArgumentCaptor<View.AccessibilityDelegate> mAccessibilityDelegateArgumentCaptor;
+
+ private DreamAccessibility mDreamAccessibility;
+ private static final String CUSTOM_ACTION = "Custom Action";
+ private static final String EXISTING_ACTION = "Existing Action";
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mDreamAccessibility = new DreamAccessibility(mContext, mView);
+
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getString(R.string.dream_accessibility_action_click))
+ .thenReturn(CUSTOM_ACTION);
+ }
+ /**
+ * Test to verify the configuration of accessibility actions within a view delegate.
+ */
+ @Test
+ public void testConfigureAccessibilityActions() {
+ when(mAccessibilityNodeInfo.getActionList()).thenReturn(new ArrayList<>());
+
+ mDreamAccessibility.updateAccessibilityConfiguration(false);
+
+ verify(mView).setAccessibilityDelegate(mAccessibilityDelegateArgumentCaptor.capture());
+ View.AccessibilityDelegate capturedDelegate =
+ mAccessibilityDelegateArgumentCaptor.getValue();
+
+ capturedDelegate.onInitializeAccessibilityNodeInfo(mView, mAccessibilityNodeInfo);
+
+ verify(mAccessibilityNodeInfo).addAction(argThat(action ->
+ action.getId() == AccessibilityNodeInfo.ACTION_CLICK
+ && TextUtils.equals(action.getLabel(), CUSTOM_ACTION)));
+ }
+
+ /**
+ * Test to verify the configuration of accessibility actions within a view delegate,
+ * specifically checking the removal of an existing click action and addition
+ * of a new custom action.
+ */
+ @Test
+ public void testConfigureAccessibilityActions_RemovesExistingClickAction() {
+ AccessibilityNodeInfo.AccessibilityAction existingAction =
+ new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK,
+ EXISTING_ACTION);
+ when(mAccessibilityNodeInfo.getActionList())
+ .thenReturn(Collections.singletonList(existingAction));
+
+ mDreamAccessibility.updateAccessibilityConfiguration(false);
+
+ verify(mView).setAccessibilityDelegate(mAccessibilityDelegateArgumentCaptor.capture());
+ View.AccessibilityDelegate capturedDelegate =
+ mAccessibilityDelegateArgumentCaptor.getValue();
+
+ capturedDelegate.onInitializeAccessibilityNodeInfo(mView, mAccessibilityNodeInfo);
+
+ verify(mAccessibilityNodeInfo).removeAction(existingAction);
+ verify(mAccessibilityNodeInfo).addAction(argThat(action ->
+ action.getId() == AccessibilityNodeInfo.ACTION_CLICK
+ && TextUtils.equals(action.getLabel(), CUSTOM_ACTION)));
+
+ }
+
+ /**
+ * Test to verify the removal of a custom accessibility action within a view delegate.
+ */
+ @Test
+ public void testRemoveCustomAccessibilityAction() {
+
+ AccessibilityNodeInfo.AccessibilityAction existingAction =
+ new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK,
+ EXISTING_ACTION);
+ when(mAccessibilityNodeInfo.getActionList())
+ .thenReturn(Collections.singletonList(existingAction));
+
+ mDreamAccessibility.updateAccessibilityConfiguration(false);
+ verify(mView).setAccessibilityDelegate(mAccessibilityDelegateArgumentCaptor.capture());
+ View.AccessibilityDelegate capturedDelegate =
+ mAccessibilityDelegateArgumentCaptor.getValue();
+ when(mView.getAccessibilityDelegate()).thenReturn(capturedDelegate);
+ clearInvocations(mView);
+
+ mDreamAccessibility.updateAccessibilityConfiguration(true);
+ verify(mView).setAccessibilityDelegate(null);
+ }
+
+ /**
+ * Test to verify the removal of custom accessibility action is not called if delegate is not
+ * set by the dreamService.
+ */
+ @Test
+ public void testRemoveCustomAccessibility_DoesNotRemoveDelegateNotSetByDreamAccessibility() {
+ mDreamAccessibility.updateAccessibilityConfiguration(true);
+ verify(mView, never()).setAccessibilityDelegate(any());
+ }
+}
+
diff --git a/services/tests/dreamservicetests/src/com/android/server/dreams/DreamControllerTest.java b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamControllerTest.java
index db70434..88ab871 100644
--- a/services/tests/dreamservicetests/src/com/android/server/dreams/DreamControllerTest.java
+++ b/services/tests/dreamservicetests/src/com/android/server/dreams/DreamControllerTest.java
@@ -19,6 +19,8 @@
import static android.os.PowerManager.USER_ACTIVITY_EVENT_OTHER;
import static android.os.PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
@@ -270,6 +272,31 @@
eq(USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS));
}
+ @Test
+ public void setDreamHasFocus_true_dreamHasFocus() {
+ mDreamController.startDream(mToken, mDreamName, false /*isPreview*/, false /*doze*/,
+ 0 /*userId*/, null /*wakeLock*/, mOverlayName, "test" /*reason*/);
+
+ mDreamController.setDreamHasFocus(true);
+ assertTrue(mDreamController.dreamHasFocus());
+ }
+
+ @Test
+ public void setDreamHasFocus_false_dreamDoesNotHaveFocus() {
+ mDreamController.startDream(mToken, mDreamName, false /*isPreview*/, false /*doze*/,
+ 0 /*userId*/, null /*wakeLock*/, mOverlayName, "test" /*reason*/);
+
+ mDreamController.setDreamHasFocus(false);
+ assertFalse(mDreamController.dreamHasFocus());
+ }
+
+ @Test
+ public void setDreamHasFocus_notDreaming_dreamDoesNotHaveFocus() {
+ mDreamController.setDreamHasFocus(true);
+ // Dream still doesn't have focus because it was never started.
+ assertFalse(mDreamController.dreamHasFocus());
+ }
+
private ServiceConnection captureServiceConnection() {
verify(mContext).bindServiceAsUser(any(), mServiceConnectionACaptor.capture(), anyInt(),
any());
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index 697548c..4a21645 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -25,6 +25,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.android.server.RescueParty.DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN;
import static com.android.server.RescueParty.LEVEL_FACTORY_RESET;
import static com.android.server.RescueParty.RESCUE_LEVEL_FACTORY_RESET;
@@ -103,8 +104,6 @@
private static final String PROP_DISABLE_FACTORY_RESET_FLAG =
"persist.device_config.configuration.disable_rescue_party_factory_reset";
- private static final int THROTTLING_DURATION_MIN = 10;
-
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -228,6 +227,9 @@
setCrashRecoveryPropRescueBootCount(0);
SystemProperties.set(RescueParty.PROP_ENABLE_RESCUE, Boolean.toString(true));
SystemProperties.set(PROP_DEVICE_CONFIG_DISABLE_FLAG, Boolean.toString(false));
+
+ // enable flag resets for tests
+ mSetFlagsRule.enableFlags(Flags.FLAG_ALLOW_RESCUE_PARTY_FLAG_RESETS);
}
@After
@@ -312,6 +314,9 @@
@Test
public void testPersistentAppCrashDetectionWithExecutionForAllRescueLevels() {
+ // this is old test where the flag needs to be disabled
+ mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+
noteAppCrash(1, true);
verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, /*resetNamespaces=*/ null,
@@ -378,6 +383,9 @@
@Test
public void testNonPersistentAppOnlyPerformsFlagResets() {
+ // this is old test where the flag needs to be disabled
+ mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+
noteAppCrash(1, false);
verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, /*resetNamespaces=*/ null,
@@ -628,7 +636,8 @@
public void testThrottlingOnBootFailures() {
setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
- long beforeTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN - 1);
+ long beforeTimeout = now - TimeUnit.MINUTES.toMillis(
+ DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN - 1);
setCrashRecoveryPropLastFactoryReset(beforeTimeout);
for (int i = 1; i <= LEVEL_FACTORY_RESET; i++) {
noteBoot(i);
@@ -641,7 +650,8 @@
mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
- long beforeTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN - 1);
+ long beforeTimeout = now - TimeUnit.MINUTES.toMillis(
+ DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN - 1);
setCrashRecoveryPropLastFactoryReset(beforeTimeout);
for (int i = 1; i <= RESCUE_LEVEL_FACTORY_RESET; i++) {
noteBoot(i);
@@ -653,7 +663,8 @@
public void testThrottlingOnAppCrash() {
setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
- long beforeTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN - 1);
+ long beforeTimeout = now - TimeUnit.MINUTES.toMillis(
+ DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN - 1);
setCrashRecoveryPropLastFactoryReset(beforeTimeout);
for (int i = 0; i <= LEVEL_FACTORY_RESET; i++) {
noteAppCrash(i + 1, true);
@@ -666,7 +677,8 @@
mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
- long beforeTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN - 1);
+ long beforeTimeout = now - TimeUnit.MINUTES.toMillis(
+ DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN - 1);
setCrashRecoveryPropLastFactoryReset(beforeTimeout);
for (int i = 0; i <= RESCUE_LEVEL_FACTORY_RESET; i++) {
noteAppCrash(i + 1, true);
@@ -678,7 +690,8 @@
public void testNotThrottlingAfterTimeoutOnBootFailures() {
setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
- long afterTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN + 1);
+ long afterTimeout = now - TimeUnit.MINUTES.toMillis(
+ DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN + 1);
setCrashRecoveryPropLastFactoryReset(afterTimeout);
for (int i = 1; i <= LEVEL_FACTORY_RESET; i++) {
noteBoot(i);
@@ -691,7 +704,8 @@
mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
- long afterTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN + 1);
+ long afterTimeout = now - TimeUnit.MINUTES.toMillis(
+ DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN + 1);
setCrashRecoveryPropLastFactoryReset(afterTimeout);
for (int i = 1; i <= RESCUE_LEVEL_FACTORY_RESET; i++) {
noteBoot(i);
@@ -703,7 +717,8 @@
public void testNotThrottlingAfterTimeoutOnAppCrash() {
setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
- long afterTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN + 1);
+ long afterTimeout = now - TimeUnit.MINUTES.toMillis(
+ DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN + 1);
setCrashRecoveryPropLastFactoryReset(afterTimeout);
for (int i = 0; i <= LEVEL_FACTORY_RESET; i++) {
noteAppCrash(i + 1, true);
@@ -716,7 +731,8 @@
mSetFlagsRule.enableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
setCrashRecoveryPropAttemptingReboot(false);
long now = System.currentTimeMillis();
- long afterTimeout = now - TimeUnit.MINUTES.toMillis(THROTTLING_DURATION_MIN + 1);
+ long afterTimeout = now - TimeUnit.MINUTES.toMillis(
+ DEFAULT_FACTORY_RESET_THROTTLE_DURATION_MIN + 1);
setCrashRecoveryPropLastFactoryReset(afterTimeout);
for (int i = 0; i <= RESCUE_LEVEL_FACTORY_RESET; i++) {
noteAppCrash(i + 1, true);
@@ -794,6 +810,9 @@
@Test
public void testHealthCheckLevels() {
+ // this is old test where the flag needs to be disabled
+ mSetFlagsRule.disableFlags(Flags.FLAG_RECOVERABILITY_DETECTION);
+
RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext);
// Ensure that no action is taken for cases where the failure reason is unknown
diff --git a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
index 124ae20..a20d935 100644
--- a/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/SensitiveContentProtectionManagerServiceNotificationTest.java
@@ -16,15 +16,18 @@
package com.android.server;
+import static android.permission.flags.Flags.FLAG_SENSITIVE_CONTENT_METRICS_BUGFIX;
import static android.permission.flags.Flags.FLAG_SENSITIVE_NOTIFICATION_APP_PROTECTION;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
@@ -34,6 +37,7 @@
import android.media.projection.MediaProjectionInfo;
import android.media.projection.MediaProjectionManager;
import android.os.Process;
+import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
@@ -309,6 +313,26 @@
}
@Test
+ @RequiresFlagsDisabled(FLAG_SENSITIVE_CONTENT_METRICS_BUGFIX)
+ public void mediaProjectionOnStart_flagDisabled_neverSetBlockScreenCaptureForAppsSessionId() {
+ setupSensitiveNotification();
+
+ mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
+
+ verify(mWindowManager, never()).setBlockScreenCaptureForAppsSessionId(anyLong());
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_SENSITIVE_CONTENT_METRICS_BUGFIX)
+ public void mediaProjectionOnStart_setBlockScreenCaptureForAppsSessionId() {
+ setupSensitiveNotification();
+
+ mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
+
+ verify(mWindowManager).setBlockScreenCaptureForAppsSessionId(anyLong());
+ }
+
+ @Test
public void mediaProjectionOnStart_onProjectionStart_setWmBlockedPackages() {
ArraySet<PackageInfo> expectedBlockedPackages = setupSensitiveNotification();
@@ -323,7 +347,7 @@
mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(any());
}
@Test
@@ -332,7 +356,7 @@
mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(any());
}
@Test
@@ -400,7 +424,7 @@
mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(any());
}
@Test
@@ -411,7 +435,7 @@
mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(any());
}
@Test
@@ -422,7 +446,7 @@
mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(any());
}
@Test
@@ -435,7 +459,7 @@
mMediaProjectionCallbackCaptor.getValue().onStart(createMediaProjectionInfo());
- verifyZeroInteractions(mWindowManager);
+ verify(mWindowManager, never()).addBlockScreenCaptureForApps(any());
}
@Test
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsCollectorTest.java
new file mode 100644
index 0000000..8b1d423
--- /dev/null
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsCollectorTest.java
@@ -0,0 +1,416 @@
+/*
+ * Copyright (C) 2024 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.power.stats;
+
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.ROAMING_NO;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerType;
+import android.net.NetworkStats;
+import android.net.wifi.WifiManager;
+import android.os.BatteryConsumer;
+import android.os.BatteryStatsManager;
+import android.os.Handler;
+import android.os.WorkSource;
+import android.os.connectivity.WifiActivityEnergyInfo;
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.util.IndentingPrintWriter;
+import android.util.SparseArray;
+
+import com.android.internal.os.Clock;
+import com.android.internal.os.PowerStats;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.IntSupplier;
+import java.util.function.Supplier;
+
+public class WifiPowerStatsCollectorTest {
+ private static final int APP_UID1 = 42;
+ private static final int APP_UID2 = 24;
+ private static final int APP_UID3 = 44;
+ private static final int ISOLATED_UID = 99123;
+
+ @Rule(order = 0)
+ public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+ .setProvideMainThread(true)
+ .build();
+
+ @Rule(order = 1)
+ public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
+ .setPowerStatsThrottlePeriodMillis(BatteryConsumer.POWER_COMPONENT_WIFI, 1000);
+
+ private MockBatteryStatsImpl mBatteryStats;
+
+ private final MockClock mClock = mStatsRule.getMockClock();
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private WifiManager mWifiManager;
+ @Mock
+ private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
+ @Mock
+ private Supplier<NetworkStats> mNetworkStatsSupplier;
+ @Mock
+ private PowerStatsUidResolver mPowerStatsUidResolver;
+
+ private NetworkStats mNetworkStats;
+ private List<NetworkStats.Entry> mNetworkStatsEntries;
+
+ private static class ScanTimes {
+ public long scanTimeMs;
+ public long batchScanTimeMs;
+ }
+
+ private final SparseArray<ScanTimes> mScanTimes = new SparseArray<>();
+ private long mWifiActiveDuration;
+
+ private final WifiPowerStatsCollector.WifiStatsRetriever mWifiStatsRetriever =
+ new WifiPowerStatsCollector.WifiStatsRetriever() {
+ @Override
+ public void retrieveWifiScanTimes(Callback callback) {
+ for (int i = 0; i < mScanTimes.size(); i++) {
+ int uid = mScanTimes.keyAt(i);
+ ScanTimes scanTimes = mScanTimes.valueAt(i);
+ callback.onWifiScanTime(uid, scanTimes.scanTimeMs, scanTimes.batchScanTimeMs);
+ }
+ }
+
+ @Override
+ public long getWifiActiveDuration() {
+ return mWifiActiveDuration;
+ }
+ };
+
+ private final List<PowerStats> mRecordedPowerStats = new ArrayList<>();
+
+ private WifiPowerStatsCollector.Injector mInjector = new WifiPowerStatsCollector.Injector() {
+ @Override
+ public Handler getHandler() {
+ return mStatsRule.getHandler();
+ }
+
+ @Override
+ public Clock getClock() {
+ return mStatsRule.getMockClock();
+ }
+
+ @Override
+ public PowerStatsUidResolver getUidResolver() {
+ return mPowerStatsUidResolver;
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return mPackageManager;
+ }
+
+ @Override
+ public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
+ return mConsumedEnergyRetriever;
+ }
+
+ @Override
+ public IntSupplier getVoltageSupplier() {
+ return () -> 3500;
+ }
+
+ @Override
+ public Supplier<NetworkStats> getWifiNetworkStatsSupplier() {
+ return mNetworkStatsSupplier;
+ }
+
+ @Override
+ public WifiPowerStatsCollector.WifiStatsRetriever getWifiStatsRetriever() {
+ return mWifiStatsRetriever;
+ }
+
+ @Override
+ public WifiManager getWifiManager() {
+ return mWifiManager;
+ }
+ };
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)).thenReturn(true);
+ when(mPowerStatsUidResolver.mapUid(anyInt())).thenAnswer(invocation -> {
+ int uid = invocation.getArgument(0);
+ if (uid == ISOLATED_UID) {
+ return APP_UID2;
+ } else {
+ return uid;
+ }
+ });
+ mBatteryStats = mStatsRule.getBatteryStats();
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void triggering() throws Throwable {
+ PowerStatsCollector collector = mBatteryStats.getPowerStatsCollector(
+ BatteryConsumer.POWER_COMPONENT_WIFI);
+ collector.addConsumer(mRecordedPowerStats::add);
+
+ mBatteryStats.setPowerStatsCollectorEnabled(BatteryConsumer.POWER_COMPONENT_WIFI, true);
+
+ mockWifiActivityInfo(1000, 2000, 3000, 600, 100);
+
+ // This should trigger a sample collection to establish a baseline
+ mBatteryStats.onSystemReady(mContext);
+
+ mStatsRule.waitForBackgroundThread();
+ assertThat(mRecordedPowerStats).hasSize(1);
+
+ mRecordedPowerStats.clear();
+ mStatsRule.setTime(20000, 20000);
+ mBatteryStats.noteWifiOnLocked(mClock.realtime, mClock.uptime);
+ mStatsRule.waitForBackgroundThread();
+ assertThat(mRecordedPowerStats).hasSize(1);
+
+ mRecordedPowerStats.clear();
+ mStatsRule.setTime(40000, 40000);
+ mBatteryStats.noteWifiOffLocked(mClock.realtime, mClock.uptime);
+ mStatsRule.waitForBackgroundThread();
+ assertThat(mRecordedPowerStats).hasSize(1);
+
+ mRecordedPowerStats.clear();
+ mStatsRule.setTime(50000, 50000);
+ mBatteryStats.noteWifiRunningLocked(new WorkSource(APP_UID1), mClock.realtime,
+ mClock.uptime);
+ mStatsRule.waitForBackgroundThread();
+ assertThat(mRecordedPowerStats).hasSize(1);
+
+ mRecordedPowerStats.clear();
+ mStatsRule.setTime(60000, 60000);
+ mBatteryStats.noteWifiStoppedLocked(new WorkSource(APP_UID1), mClock.realtime,
+ mClock.uptime);
+ mStatsRule.waitForBackgroundThread();
+ assertThat(mRecordedPowerStats).hasSize(1);
+
+ mRecordedPowerStats.clear();
+ mStatsRule.setTime(70000, 70000);
+ mBatteryStats.noteWifiStateLocked(BatteryStatsManager.WIFI_STATE_ON_CONNECTED_STA,
+ "mywyfy", mClock.realtime);
+ mStatsRule.waitForBackgroundThread();
+ assertThat(mRecordedPowerStats).hasSize(1);
+ }
+
+ @Test
+ public void collectStats_powerReportingSupported() throws Throwable {
+ PowerStats powerStats = collectPowerStats(true);
+ assertThat(powerStats.durationMs).isEqualTo(7500);
+
+ PowerStats.Descriptor descriptor = powerStats.descriptor;
+ WifiPowerStatsLayout layout = new WifiPowerStatsLayout(descriptor);
+ assertThat(layout.isPowerReportingSupported()).isTrue();
+ assertThat(layout.getDeviceRxTime(powerStats.stats)).isEqualTo(6000);
+ assertThat(layout.getDeviceTxTime(powerStats.stats)).isEqualTo(1000);
+ assertThat(layout.getDeviceScanTime(powerStats.stats)).isEqualTo(200);
+ assertThat(layout.getDeviceIdleTime(powerStats.stats)).isEqualTo(300);
+ assertThat(layout.getConsumedEnergy(powerStats.stats, 0))
+ .isEqualTo((64321 - 10000) * 1000 / 3500);
+
+ verifyUidStats(powerStats);
+ }
+
+ @Test
+ public void collectStats_powerReportingUnsupported() {
+ PowerStats powerStats = collectPowerStats(false);
+ assertThat(powerStats.durationMs).isEqualTo(13200);
+
+ PowerStats.Descriptor descriptor = powerStats.descriptor;
+ WifiPowerStatsLayout layout = new WifiPowerStatsLayout(descriptor);
+ assertThat(layout.isPowerReportingSupported()).isFalse();
+ assertThat(layout.getDeviceActiveTime(powerStats.stats)).isEqualTo(7500);
+ assertThat(layout.getDeviceBasicScanTime(powerStats.stats)).isEqualTo(234 + 100 + 300);
+ assertThat(layout.getDeviceBatchedScanTime(powerStats.stats)).isEqualTo(345 + 200 + 400);
+ assertThat(layout.getConsumedEnergy(powerStats.stats, 0))
+ .isEqualTo((64321 - 10000) * 1000 / 3500);
+
+ verifyUidStats(powerStats);
+ }
+
+ private void verifyUidStats(PowerStats powerStats) {
+ WifiPowerStatsLayout layout = new WifiPowerStatsLayout(powerStats.descriptor);
+ assertThat(powerStats.uidStats.size()).isEqualTo(2);
+ long[] actual1 = powerStats.uidStats.get(APP_UID1);
+ assertThat(layout.getUidRxBytes(actual1)).isEqualTo(1000);
+ assertThat(layout.getUidTxBytes(actual1)).isEqualTo(2000);
+ assertThat(layout.getUidRxPackets(actual1)).isEqualTo(100);
+ assertThat(layout.getUidTxPackets(actual1)).isEqualTo(200);
+ assertThat(layout.getUidScanTime(actual1)).isEqualTo(234);
+ assertThat(layout.getUidBatchedScanTime(actual1)).isEqualTo(345);
+
+ // Combines APP_UID2 and ISOLATED_UID
+ long[] actual2 = powerStats.uidStats.get(APP_UID2);
+ assertThat(layout.getUidRxBytes(actual2)).isEqualTo(6000);
+ assertThat(layout.getUidTxBytes(actual2)).isEqualTo(3000);
+ assertThat(layout.getUidRxPackets(actual2)).isEqualTo(60);
+ assertThat(layout.getUidTxPackets(actual2)).isEqualTo(30);
+ assertThat(layout.getUidScanTime(actual2)).isEqualTo(100 + 300);
+ assertThat(layout.getUidBatchedScanTime(actual2)).isEqualTo(200 + 400);
+
+ assertThat(powerStats.uidStats.get(ISOLATED_UID)).isNull();
+ assertThat(powerStats.uidStats.get(APP_UID3)).isNull();
+ }
+
+ @Test
+ public void dump() throws Throwable {
+ PowerStats powerStats = collectPowerStats(true);
+ StringWriter sw = new StringWriter();
+ IndentingPrintWriter pw = new IndentingPrintWriter(sw);
+ powerStats.dump(pw);
+ pw.flush();
+ String dump = sw.toString();
+ assertThat(dump).contains("duration=7500");
+ assertThat(dump).contains(
+ "stats=[6000, 1000, 300, 200, 634, 945, " + ((64321 - 10000) * 1000 / 3500)
+ + ", 0, 0]");
+ assertThat(dump).contains("UID 24: [6000, 3000, 60, 30, 400, 600, 0]");
+ assertThat(dump).contains("UID 42: [1000, 2000, 100, 200, 234, 345, 0]");
+ }
+
+ private PowerStats collectPowerStats(boolean hasPowerReporting) {
+ when(mWifiManager.isEnhancedPowerReportingSupported()).thenReturn(hasPowerReporting);
+
+ WifiPowerStatsCollector collector = new WifiPowerStatsCollector(mInjector, 0);
+ collector.setEnabled(true);
+
+ when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.WIFI))
+ .thenReturn(new int[]{777});
+
+ if (hasPowerReporting) {
+ mockWifiActivityInfo(1000, 600, 100, 2000, 3000);
+ } else {
+ mWifiActiveDuration = 5700;
+ }
+ mockNetworkStats(1000);
+ mockNetworkStatsEntry(APP_UID1, 4321, 321, 1234, 23);
+ mockNetworkStatsEntry(APP_UID2, 4000, 40, 2000, 20);
+ mockNetworkStatsEntry(ISOLATED_UID, 2000, 20, 1000, 10);
+ mockNetworkStatsEntry(APP_UID3, 314, 281, 314, 281);
+ mockWifiScanTimes(APP_UID1, 1000, 2000);
+ mockWifiScanTimes(APP_UID2, 3000, 4000);
+ mockWifiScanTimes(ISOLATED_UID, 5000, 6000);
+
+ when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
+ .thenReturn(new long[]{10000});
+
+ collector.collectStats();
+
+ if (hasPowerReporting) {
+ mockWifiActivityInfo(1100, 6600, 1100, 2200, 3300);
+ } else {
+ mWifiActiveDuration = 13200;
+ }
+ mockNetworkStats(1100);
+ mockNetworkStatsEntry(APP_UID1, 5321, 421, 3234, 223);
+ mockNetworkStatsEntry(APP_UID2, 8000, 80, 4000, 40);
+ mockNetworkStatsEntry(ISOLATED_UID, 4000, 40, 2000, 20);
+ mockNetworkStatsEntry(APP_UID3, 314, 281, 314, 281); // Unchanged
+ mockWifiScanTimes(APP_UID1, 1234, 2345);
+ mockWifiScanTimes(APP_UID2, 3100, 4200);
+ mockWifiScanTimes(ISOLATED_UID, 5300, 6400);
+
+ when(mConsumedEnergyRetriever.getConsumedEnergyUws(eq(new int[]{777})))
+ .thenReturn(new long[]{64321});
+
+ mStatsRule.setTime(20000, 20000);
+ return collector.collectStats();
+ }
+
+ private void mockWifiActivityInfo(long timestamp, long rxTimeMs, long txTimeMs, int scanTimeMs,
+ int idleTimeMs) {
+ int stackState = 0;
+ WifiActivityEnergyInfo info = new WifiActivityEnergyInfo(timestamp, stackState, txTimeMs,
+ rxTimeMs, scanTimeMs, idleTimeMs);
+ doAnswer(invocation -> {
+ WifiManager.OnWifiActivityEnergyInfoListener listener = invocation.getArgument(1);
+ listener.onWifiActivityEnergyInfo(info);
+ return null;
+ }).when(mWifiManager).getWifiActivityEnergyInfoAsync(any(), any());
+ }
+
+ private void mockNetworkStats(long elapsedRealtime) {
+ if (RavenwoodRule.isOnRavenwood()) {
+ mNetworkStats = mock(NetworkStats.class);
+ ArrayList<NetworkStats.Entry> networkStatsEntries = new ArrayList<>();
+ when(mNetworkStats.iterator()).thenAnswer(inv -> networkStatsEntries.iterator());
+ mNetworkStatsEntries = networkStatsEntries;
+ } else {
+ mNetworkStats = new NetworkStats(elapsedRealtime, 1);
+ }
+ when(mNetworkStatsSupplier.get()).thenReturn(mNetworkStats);
+ }
+
+ private void mockNetworkStatsEntry(int uid, long rxBytes, long rxPackets, long txBytes,
+ long txPackets) {
+ if (RavenwoodRule.isOnRavenwood()) {
+ NetworkStats.Entry entry = mock(NetworkStats.Entry.class);
+ when(entry.getUid()).thenReturn(uid);
+ when(entry.getMetered()).thenReturn(METERED_NO);
+ when(entry.getRoaming()).thenReturn(ROAMING_NO);
+ when(entry.getDefaultNetwork()).thenReturn(DEFAULT_NETWORK_NO);
+ when(entry.getRxBytes()).thenReturn(rxBytes);
+ when(entry.getRxPackets()).thenReturn(rxPackets);
+ when(entry.getTxBytes()).thenReturn(txBytes);
+ when(entry.getTxPackets()).thenReturn(txPackets);
+ when(entry.getOperations()).thenReturn(100L);
+ mNetworkStatsEntries.add(entry);
+ } else {
+ mNetworkStats = mNetworkStats
+ .addEntry(new NetworkStats.Entry("wifi", uid, 0, 0,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, rxBytes, rxPackets,
+ txBytes, txPackets, 100));
+ reset(mNetworkStatsSupplier);
+ when(mNetworkStatsSupplier.get()).thenReturn(mNetworkStats);
+ }
+ }
+
+ private void mockWifiScanTimes(int uid, long scanTimeMs, long batchScanTimeMs) {
+ ScanTimes scanTimes = new ScanTimes();
+ scanTimes.scanTimeMs = scanTimeMs;
+ scanTimes.batchScanTimeMs = batchScanTimeMs;
+ mScanTimes.put(uid, scanTimes);
+ }
+}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsProcessorTest.java
new file mode 100644
index 0000000..257a1a6
--- /dev/null
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/WifiPowerStatsProcessorTest.java
@@ -0,0 +1,592 @@
+/*
+ * Copyright (C) 2024 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.power.stats;
+
+import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
+import static android.net.NetworkStats.METERED_NO;
+import static android.net.NetworkStats.ROAMING_NO;
+import static android.os.BatteryConsumer.PROCESS_STATE_BACKGROUND;
+import static android.os.BatteryConsumer.PROCESS_STATE_CACHED;
+import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND;
+import static android.os.BatteryConsumer.PROCESS_STATE_FOREGROUND_SERVICE;
+
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.POWER_STATE_OTHER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_ON;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.SCREEN_STATE_OTHER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_POWER;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_PROCESS_STATE;
+import static com.android.server.power.stats.AggregatedPowerStatsConfig.STATE_SCREEN;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.power.stats.EnergyConsumerType;
+import android.net.NetworkStats;
+import android.net.wifi.WifiManager;
+import android.os.BatteryConsumer;
+import android.os.Handler;
+import android.os.Process;
+import android.os.connectivity.WifiActivityEnergyInfo;
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.util.SparseArray;
+
+import com.android.internal.os.Clock;
+import com.android.internal.os.PowerProfile;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.List;
+import java.util.function.IntSupplier;
+import java.util.function.Supplier;
+
+public class WifiPowerStatsProcessorTest {
+ @Rule(order = 0)
+ public final RavenwoodRule mRavenwood = new RavenwoodRule.Builder()
+ .setProvideMainThread(true)
+ .build();
+
+ private static final double PRECISION = 0.00001;
+ private static final int APP_UID1 = Process.FIRST_APPLICATION_UID + 42;
+ private static final int APP_UID2 = Process.FIRST_APPLICATION_UID + 101;
+ private static final int WIFI_ENERGY_CONSUMER_ID = 1;
+ private static final int VOLTAGE_MV = 3500;
+
+ @Rule(order = 1)
+ public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
+ .setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE, 360.0)
+ .setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_RX, 480.0)
+ .setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_TX, 720.0)
+ .setAveragePower(PowerProfile.POWER_WIFI_ACTIVE, 360.0)
+ .setAveragePower(PowerProfile.POWER_WIFI_SCAN, 480.0)
+ .setAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN, 720.0)
+ .initMeasuredEnergyStatsLocked();
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private PowerStatsUidResolver mPowerStatsUidResolver;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private PowerStatsCollector.ConsumedEnergyRetriever mConsumedEnergyRetriever;
+ @Mock
+ private Supplier<NetworkStats> mNetworkStatsSupplier;
+ @Mock
+ private WifiManager mWifiManager;
+
+ private static class ScanTimes {
+ public long scanTimeMs;
+ public long batchScanTimeMs;
+ }
+
+ private final SparseArray<ScanTimes> mScanTimes = new SparseArray<>();
+ private long mWifiActiveDuration;
+
+ private final WifiPowerStatsCollector.WifiStatsRetriever mWifiStatsRetriever =
+ new WifiPowerStatsCollector.WifiStatsRetriever() {
+ @Override
+ public void retrieveWifiScanTimes(Callback callback) {
+ for (int i = 0; i < mScanTimes.size(); i++) {
+ int uid = mScanTimes.keyAt(i);
+ ScanTimes scanTimes = mScanTimes.valueAt(i);
+ callback.onWifiScanTime(uid, scanTimes.scanTimeMs, scanTimes.batchScanTimeMs);
+ }
+ }
+
+ @Override
+ public long getWifiActiveDuration() {
+ return mWifiActiveDuration;
+ }
+ };
+
+ private final WifiPowerStatsCollector.Injector mInjector =
+ new WifiPowerStatsCollector.Injector() {
+ @Override
+ public Handler getHandler() {
+ return mStatsRule.getHandler();
+ }
+
+ @Override
+ public Clock getClock() {
+ return mStatsRule.getMockClock();
+ }
+
+ @Override
+ public PowerStatsUidResolver getUidResolver() {
+ return mPowerStatsUidResolver;
+ }
+
+ @Override
+ public PackageManager getPackageManager() {
+ return mPackageManager;
+ }
+
+ @Override
+ public PowerStatsCollector.ConsumedEnergyRetriever getConsumedEnergyRetriever() {
+ return mConsumedEnergyRetriever;
+ }
+
+ @Override
+ public IntSupplier getVoltageSupplier() {
+ return () -> VOLTAGE_MV;
+ }
+
+ @Override
+ public Supplier<NetworkStats> getWifiNetworkStatsSupplier() {
+ return mNetworkStatsSupplier;
+ }
+
+ @Override
+ public WifiManager getWifiManager() {
+ return mWifiManager;
+ }
+
+ @Override
+ public WifiPowerStatsCollector.WifiStatsRetriever getWifiStatsRetriever() {
+ return mWifiStatsRetriever;
+ }
+ };
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI)).thenReturn(true);
+ when(mPowerStatsUidResolver.mapUid(anyInt()))
+ .thenAnswer(invocation -> invocation.getArgument(0));
+ }
+
+ @Test
+ public void powerProfileModel_powerController() {
+ when(mWifiManager.isEnhancedPowerReportingSupported()).thenReturn(true);
+
+ // No power monitoring hardware
+ when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.WIFI))
+ .thenReturn(new int[0]);
+
+ WifiPowerStatsProcessor processor =
+ new WifiPowerStatsProcessor(mStatsRule.getPowerProfile());
+
+ PowerComponentAggregatedPowerStats aggregatedStats = createAggregatedPowerStats(processor);
+
+ WifiPowerStatsCollector collector = new WifiPowerStatsCollector(mInjector, 0);
+ collector.setEnabled(true);
+
+ // Initial empty WifiActivityEnergyInfo.
+ mockWifiActivityEnergyInfo(new WifiActivityEnergyInfo(0L,
+ WifiActivityEnergyInfo.STACK_STATE_INVALID, 0L, 0L, 0L, 0L));
+
+ // Establish a baseline
+ aggregatedStats.addPowerStats(collector.collectStats(), 0);
+
+ // Turn the screen off after 2.5 seconds
+ aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_OTHER, 2500);
+ aggregatedStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_BACKGROUND, 2500);
+ aggregatedStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND_SERVICE,
+ 5000);
+
+ // Note application network activity
+ NetworkStats networkStats = mockNetworkStats(10000, 1,
+ mockNetworkStatsEntry("wifi", APP_UID1, 0, 0,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 10000, 1500, 20000, 300, 100),
+ mockNetworkStatsEntry("wifi", APP_UID2, 0, 0,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 5000, 500, 3000, 100, 111));
+ when(mNetworkStatsSupplier.get()).thenReturn(networkStats);
+
+ mockWifiScanTimes(APP_UID1, 300, 400);
+ mockWifiScanTimes(APP_UID2, 100, 200);
+
+ mockWifiActivityEnergyInfo(new WifiActivityEnergyInfo(10000,
+ WifiActivityEnergyInfo.STACK_STATE_STATE_ACTIVE, 2000, 3000, 100, 600));
+
+ mStatsRule.setTime(10_000, 10_000);
+
+ aggregatedStats.addPowerStats(collector.collectStats(), 10_000);
+
+ processor.finish(aggregatedStats);
+
+ WifiPowerStatsLayout statsLayout =
+ new WifiPowerStatsLayout(aggregatedStats.getPowerStatsDescriptor());
+
+ // RX power = 'rx-duration * PowerProfile[wifi.controller.rx]`
+ // RX power = 3000 * 480 = 1440000 mA-ms = 0.4 mAh
+ // TX power = 'tx-duration * PowerProfile[wifi.controller.tx]`
+ // TX power = 2000 * 720 = 1440000 mA-ms = 0.4 mAh
+ // Scan power = 'scan-duration * PowerProfile[wifi.scan]`
+ // Scan power = 100 * 480 = 48000 mA-ms = 0.013333 mAh
+ // Idle power = 'idle-duration * PowerProfile[wifi.idle]`
+ // Idle power = 600 * 360 = 216000 mA-ms = 0.06 mAh
+ // Total power = RX + TX + Scan + Idle = 0.873333
+ // Screen-on - 25%
+ // Screen-off - 75%
+ double expectedPower = 0.873333;
+ long[] deviceStats = new long[aggregatedStats.getPowerStatsDescriptor().statsArrayLength];
+ aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_ON));
+ assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+ .isWithin(PRECISION).of(expectedPower * 0.25);
+
+ aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_OTHER));
+ assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+ .isWithin(PRECISION).of(expectedPower * 0.75);
+
+ // UID1 =
+ // (1500 / 2000) * 0.4 // rx
+ // + (300 / 400) * 0.4 // tx
+ // + (700 / 1000) * 0.013333 // scan (basic + batched)
+ // = 0.609333 mAh
+ double expectedPower1 = 0.609333;
+ long[] uidStats = new long[aggregatedStats.getPowerStatsDescriptor().uidStatsArrayLength];
+ aggregatedStats.getUidStats(uidStats, APP_UID1,
+ states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND));
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(expectedPower1 * 0.25);
+
+ aggregatedStats.getUidStats(uidStats, APP_UID1,
+ states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_BACKGROUND));
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(expectedPower1 * 0.25);
+
+ aggregatedStats.getUidStats(uidStats, APP_UID1,
+ states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_FOREGROUND_SERVICE));
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(expectedPower1 * 0.5);
+
+ // UID2 =
+ // (500 / 2000) * 0.4 // rx
+ // + (100 / 400) * 0.4 // tx
+ // + (300 / 1000) * 0.013333 // scan (basic + batched)
+ // = 0.204 mAh
+ double expectedPower2 = 0.204;
+ aggregatedStats.getUidStats(uidStats, APP_UID2,
+ states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED));
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(expectedPower2 * 0.25);
+
+ aggregatedStats.getUidStats(uidStats, APP_UID2,
+ states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_CACHED));
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(expectedPower2 * 0.75);
+ }
+
+ @Test
+ public void consumedEnergyModel_powerController() {
+ when(mWifiManager.isEnhancedPowerReportingSupported()).thenReturn(true);
+
+ // PowerStats hardware is available
+ when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.WIFI))
+ .thenReturn(new int[] {WIFI_ENERGY_CONSUMER_ID});
+
+ WifiPowerStatsProcessor processor =
+ new WifiPowerStatsProcessor(mStatsRule.getPowerProfile());
+
+ PowerComponentAggregatedPowerStats aggregatedStats = createAggregatedPowerStats(processor);
+
+ WifiPowerStatsCollector collector = new WifiPowerStatsCollector(mInjector, 0);
+ collector.setEnabled(true);
+
+ // Initial empty WifiActivityEnergyInfo.
+ mockWifiActivityEnergyInfo(new WifiActivityEnergyInfo(0L,
+ WifiActivityEnergyInfo.STACK_STATE_INVALID, 0L, 0L, 0L, 0L));
+
+ when(mConsumedEnergyRetriever.getConsumedEnergyUws(
+ new int[]{WIFI_ENERGY_CONSUMER_ID}))
+ .thenReturn(new long[]{0});
+
+ // Establish a baseline
+ aggregatedStats.addPowerStats(collector.collectStats(), 0);
+
+ // Turn the screen off after 2.5 seconds
+ aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_OTHER, 2500);
+ aggregatedStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_BACKGROUND, 2500);
+ aggregatedStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND_SERVICE,
+ 5000);
+
+ // Note application network activity
+ NetworkStats networkStats = mockNetworkStats(10000, 1,
+ mockNetworkStatsEntry("wifi", APP_UID1, 0, 0,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 10000, 1500, 20000, 300, 100),
+ mockNetworkStatsEntry("wifi", APP_UID2, 0, 0,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 5000, 500, 3000, 100, 111));
+ when(mNetworkStatsSupplier.get()).thenReturn(networkStats);
+
+ mockWifiScanTimes(APP_UID1, 300, 400);
+ mockWifiScanTimes(APP_UID2, 100, 200);
+
+ mockWifiActivityEnergyInfo(new WifiActivityEnergyInfo(10000,
+ WifiActivityEnergyInfo.STACK_STATE_STATE_ACTIVE, 2000, 3000, 100, 600));
+
+ mStatsRule.setTime(10_000, 10_000);
+
+ // 10 mAh represented as microWattSeconds
+ long energyUws = 10 * 3600 * VOLTAGE_MV;
+ when(mConsumedEnergyRetriever.getConsumedEnergyUws(
+ new int[]{WIFI_ENERGY_CONSUMER_ID})).thenReturn(new long[]{energyUws});
+
+ aggregatedStats.addPowerStats(collector.collectStats(), 10_000);
+
+ processor.finish(aggregatedStats);
+
+ WifiPowerStatsLayout statsLayout =
+ new WifiPowerStatsLayout(aggregatedStats.getPowerStatsDescriptor());
+
+ // All estimates are computed as in the #powerProfileModel_powerController test,
+ // except they are all scaled by the same ratio to ensure that the total estimated
+ // energy is equal to the measured energy
+ double expectedPower = 10;
+ long[] deviceStats = new long[aggregatedStats.getPowerStatsDescriptor().statsArrayLength];
+ aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_ON));
+ assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+ .isWithin(PRECISION).of(expectedPower * 0.25);
+
+ aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_OTHER));
+ assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+ .isWithin(PRECISION).of(expectedPower * 0.75);
+
+ // UID1
+ // 0.609333 // power profile model estimate
+ // 0.873333 // power profile model estimate for total power
+ // 10 // total consumed energy
+ // = 0.609333 * (10 / 0.873333) = 6.9771
+ double expectedPower1 = 6.9771;
+ long[] uidStats = new long[aggregatedStats.getPowerStatsDescriptor().uidStatsArrayLength];
+ aggregatedStats.getUidStats(uidStats, APP_UID1,
+ states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND));
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(expectedPower1 * 0.25);
+
+ aggregatedStats.getUidStats(uidStats, APP_UID1,
+ states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_BACKGROUND));
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(expectedPower1 * 0.25);
+
+ aggregatedStats.getUidStats(uidStats, APP_UID1,
+ states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_FOREGROUND_SERVICE));
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(expectedPower1 * 0.5);
+
+ // UID2
+ // 0.204 // power profile model estimate
+ // 0.873333 // power profile model estimate for total power
+ // 10 // total consumed energy
+ // = 0.204 * (10 / 0.873333) = 2.33588
+ double expectedPower2 = 2.33588;
+ aggregatedStats.getUidStats(uidStats, APP_UID2,
+ states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED));
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(expectedPower2 * 0.25);
+
+ aggregatedStats.getUidStats(uidStats, APP_UID2,
+ states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_CACHED));
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(expectedPower2 * 0.75);
+ }
+
+ @Test
+ public void powerProfileModel_noPowerController() {
+ when(mWifiManager.isEnhancedPowerReportingSupported()).thenReturn(false);
+
+ // No power monitoring hardware
+ when(mConsumedEnergyRetriever.getEnergyConsumerIds(EnergyConsumerType.WIFI))
+ .thenReturn(new int[0]);
+
+ WifiPowerStatsProcessor processor =
+ new WifiPowerStatsProcessor(mStatsRule.getPowerProfile());
+
+ PowerComponentAggregatedPowerStats aggregatedStats = createAggregatedPowerStats(processor);
+
+ WifiPowerStatsCollector collector = new WifiPowerStatsCollector(mInjector, 0);
+ collector.setEnabled(true);
+
+ // Establish a baseline
+ aggregatedStats.addPowerStats(collector.collectStats(), 0);
+
+ // Turn the screen off after 2.5 seconds
+ aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_OTHER, 2500);
+ aggregatedStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_BACKGROUND, 2500);
+ aggregatedStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND_SERVICE,
+ 5000);
+
+ // Note application network activity
+ NetworkStats networkStats = mockNetworkStats(10000, 1,
+ mockNetworkStatsEntry("wifi", APP_UID1, 0, 0,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 10000, 1500, 20000, 300, 100),
+ mockNetworkStatsEntry("wifi", APP_UID2, 0, 0,
+ METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO, 5000, 500, 3000, 100, 111));
+ when(mNetworkStatsSupplier.get()).thenReturn(networkStats);
+
+ mScanTimes.clear();
+ mWifiActiveDuration = 8000;
+ mockWifiScanTimes(APP_UID1, 300, 400);
+ mockWifiScanTimes(APP_UID2, 100, 200);
+
+ mStatsRule.setTime(10_000, 10_000);
+
+ aggregatedStats.addPowerStats(collector.collectStats(), 10_000);
+
+ processor.finish(aggregatedStats);
+
+ WifiPowerStatsLayout statsLayout =
+ new WifiPowerStatsLayout(aggregatedStats.getPowerStatsDescriptor());
+
+ // Total active power = 'active-duration * PowerProfile[wifi.on]`
+ // active = 8000 * 360 = 2880000 mA-ms = 0.8 mAh
+ // UID1 rxPackets + txPackets = 1800
+ // UID2 rxPackets + txPackets = 600
+ // Total rx+tx packets = 2400
+ // Total scan power = `scan-duration * PowerProfile[wifi.scan]`
+ // scan = (100 + 300) * 480 = 192000 mA-ms = 0.05333 mAh
+ // Total batch scan power = `(200 + 400) * PowerProfile[wifi.batchedscan]`
+ // bscan = (200 + 400) * 720 = 432000 mA-ms = 0.12 mAh
+ //
+ // Expected power = active + scan + bscan = 0.97333
+ double expectedPower = 0.97333;
+ long[] deviceStats = new long[aggregatedStats.getPowerStatsDescriptor().statsArrayLength];
+ aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_ON));
+ assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+ .isWithin(PRECISION).of(expectedPower * 0.25);
+
+ aggregatedStats.getDeviceStats(deviceStats, states(POWER_STATE_OTHER, SCREEN_STATE_OTHER));
+ assertThat(statsLayout.getDevicePowerEstimate(deviceStats))
+ .isWithin(PRECISION).of(expectedPower * 0.75);
+
+ // UID1 =
+ // (1800 / 2400) * 0.8 // active
+ // + (300 / 400) * 0.05333 // scan
+ // + (400 / 600) * 0.12 // batched scan
+ // = 0.72 mAh
+ double expectedPower1 = 0.72;
+ long[] uidStats = new long[aggregatedStats.getPowerStatsDescriptor().uidStatsArrayLength];
+ aggregatedStats.getUidStats(uidStats, APP_UID1,
+ states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_FOREGROUND));
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(expectedPower1 * 0.25);
+
+ aggregatedStats.getUidStats(uidStats, APP_UID1,
+ states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_BACKGROUND));
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(expectedPower1 * 0.25);
+
+ aggregatedStats.getUidStats(uidStats, APP_UID1,
+ states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_FOREGROUND_SERVICE));
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(expectedPower1 * 0.5);
+
+ // UID2 =
+ // (600 / 2400) * 0.8 // active
+ // + (100 / 400) * 0.05333 // scan
+ // + (200 / 600) * 0.12 // batched scan
+ // = 0.253333 mAh
+ double expectedPower2 = 0.25333;
+ aggregatedStats.getUidStats(uidStats, APP_UID2,
+ states(POWER_STATE_OTHER, SCREEN_STATE_ON, PROCESS_STATE_CACHED));
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(expectedPower2 * 0.25);
+
+ aggregatedStats.getUidStats(uidStats, APP_UID2,
+ states(POWER_STATE_OTHER, SCREEN_STATE_OTHER, PROCESS_STATE_CACHED));
+ assertThat(statsLayout.getUidPowerEstimate(uidStats))
+ .isWithin(PRECISION).of(expectedPower2 * 0.75);
+ }
+
+ private static PowerComponentAggregatedPowerStats createAggregatedPowerStats(
+ WifiPowerStatsProcessor processor) {
+ AggregatedPowerStatsConfig.PowerComponent config =
+ new AggregatedPowerStatsConfig.PowerComponent(BatteryConsumer.POWER_COMPONENT_WIFI)
+ .trackDeviceStates(STATE_POWER, STATE_SCREEN)
+ .trackUidStates(STATE_POWER, STATE_SCREEN, STATE_PROCESS_STATE)
+ .setProcessor(processor);
+
+ PowerComponentAggregatedPowerStats aggregatedStats =
+ new PowerComponentAggregatedPowerStats(
+ new AggregatedPowerStats(mock(AggregatedPowerStatsConfig.class)), config);
+
+ aggregatedStats.setState(STATE_POWER, POWER_STATE_OTHER, 0);
+ aggregatedStats.setState(STATE_SCREEN, SCREEN_STATE_ON, 0);
+ aggregatedStats.setUidState(APP_UID1, STATE_PROCESS_STATE, PROCESS_STATE_FOREGROUND, 0);
+ aggregatedStats.setUidState(APP_UID2, STATE_PROCESS_STATE, PROCESS_STATE_CACHED, 0);
+
+ return aggregatedStats;
+ }
+
+ private int[] states(int... states) {
+ return states;
+ }
+
+ private void mockWifiActivityEnergyInfo(WifiActivityEnergyInfo waei) {
+ doAnswer(invocation -> {
+ WifiManager.OnWifiActivityEnergyInfoListener
+ listener = invocation.getArgument(1);
+ listener.onWifiActivityEnergyInfo(waei);
+ return null;
+ }).when(mWifiManager).getWifiActivityEnergyInfoAsync(any(), any());
+ }
+
+ private NetworkStats mockNetworkStats(int elapsedTime, int initialSize,
+ NetworkStats.Entry... entries) {
+ NetworkStats stats;
+ if (RavenwoodRule.isOnRavenwood()) {
+ stats = mock(NetworkStats.class);
+ when(stats.iterator()).thenAnswer(inv -> List.of(entries).iterator());
+ } else {
+ stats = new NetworkStats(elapsedTime, initialSize);
+ for (NetworkStats.Entry entry : entries) {
+ stats = stats.addEntry(entry);
+ }
+ }
+ return stats;
+ }
+
+ private static NetworkStats.Entry mockNetworkStatsEntry(@Nullable String iface, int uid,
+ int set, int tag, int metered, int roaming, int defaultNetwork, long rxBytes,
+ long rxPackets, long txBytes, long txPackets, long operations) {
+ if (RavenwoodRule.isOnRavenwood()) {
+ NetworkStats.Entry entry = mock(NetworkStats.Entry.class);
+ when(entry.getUid()).thenReturn(uid);
+ when(entry.getMetered()).thenReturn(metered);
+ when(entry.getRoaming()).thenReturn(roaming);
+ when(entry.getDefaultNetwork()).thenReturn(defaultNetwork);
+ when(entry.getRxBytes()).thenReturn(rxBytes);
+ when(entry.getRxPackets()).thenReturn(rxPackets);
+ when(entry.getTxBytes()).thenReturn(txBytes);
+ when(entry.getTxPackets()).thenReturn(txPackets);
+ when(entry.getOperations()).thenReturn(operations);
+ return entry;
+ } else {
+ return new NetworkStats.Entry(iface, uid, set, tag, metered,
+ roaming, defaultNetwork, rxBytes, rxPackets, txBytes, txPackets, operations);
+ }
+ }
+
+ private void mockWifiScanTimes(int uid, long scanTimeMs, long batchScanTimeMs) {
+ ScanTimes scanTimes = new ScanTimes();
+ scanTimes.scanTimeMs = scanTimeMs;
+ scanTimes.batchScanTimeMs = batchScanTimeMs;
+ mScanTimes.put(uid, scanTimes);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java
index b487dc6..c970a3e 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsActiveWatcherTest.java
@@ -16,7 +16,8 @@
package com.android.server.appop;
-import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CAMERA;
import static com.google.common.truth.Truth.assertThat;
@@ -31,6 +32,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import android.Manifest;
import android.app.AppOpsManager;
import android.app.AppOpsManager.OnOpActiveChangedListener;
import android.companion.virtual.VirtualDeviceManager;
@@ -38,7 +40,8 @@
import android.content.AttributionSource;
import android.content.Context;
import android.os.Process;
-import android.virtualdevice.cts.common.FakeAssociationRule;
+import android.permission.PermissionManager;
+import android.virtualdevice.cts.common.VirtualDeviceRule;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -49,7 +52,6 @@
import org.junit.runner.RunWith;
import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
/**
* Tests app ops version upgrades
@@ -59,7 +61,13 @@
public class AppOpsActiveWatcherTest {
@Rule
- public FakeAssociationRule mFakeAssociationRule = new FakeAssociationRule();
+ public VirtualDeviceRule virtualDeviceRule =
+ VirtualDeviceRule.withAdditionalPermissions(
+ Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+ Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
+ Manifest.permission.CREATE_VIRTUAL_DEVICE,
+ Manifest.permission.GET_APP_OPS_STATS
+ );
private static final long NOTIFICATION_TIMEOUT_MILLIS = 5000;
@Test
@@ -145,20 +153,28 @@
@Test
public void testWatchActiveOpsForExternalDevice() {
- final VirtualDeviceManager virtualDeviceManager = getContext().getSystemService(
- VirtualDeviceManager.class);
- AtomicInteger virtualDeviceId = new AtomicInteger();
- runWithShellPermissionIdentity(() -> {
- final VirtualDeviceManager.VirtualDevice virtualDevice =
- virtualDeviceManager.createVirtualDevice(
- mFakeAssociationRule.getAssociationInfo().getId(),
- new VirtualDeviceParams.Builder().setName("virtual_device").build());
- virtualDeviceId.set(virtualDevice.getDeviceId());
- });
+ VirtualDeviceManager.VirtualDevice virtualDevice =
+ virtualDeviceRule.createManagedVirtualDevice(
+ new VirtualDeviceParams.Builder()
+ .setDevicePolicy(POLICY_TYPE_CAMERA, DEVICE_POLICY_CUSTOM)
+ .build()
+ );
+
+ PermissionManager permissionManager =
+ getContext().getSystemService(PermissionManager.class);
+
+ // Unlike runtime permission being automatically granted to the default device, we need to
+ // grant camera permission to the external device first before we can start op.
+ permissionManager.grantRuntimePermission(
+ getContext().getOpPackageName(),
+ Manifest.permission.CAMERA,
+ virtualDevice.getPersistentDeviceId()
+ );
+
final OnOpActiveChangedListener listener = mock(OnOpActiveChangedListener.class);
AttributionSource attributionSource = new AttributionSource(Process.myUid(),
getContext().getOpPackageName(), getContext().getAttributionTag(),
- virtualDeviceId.get());
+ virtualDevice.getDeviceId());
final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
appOpsManager.startWatchingActive(new String[]{AppOpsManager.OPSTR_CAMERA,
@@ -171,7 +187,7 @@
verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
.times(1)).onOpActiveChanged(eq(AppOpsManager.OPSTR_CAMERA),
eq(Process.myUid()), eq(getContext().getOpPackageName()),
- eq(getContext().getAttributionTag()), eq(virtualDeviceId.get()), eq(true),
+ eq(getContext().getAttributionTag()), eq(virtualDevice.getDeviceId()), eq(true),
eq(AppOpsManager.ATTRIBUTION_FLAGS_NONE),
eq(AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE));
verifyNoMoreInteractions(listener);
@@ -182,7 +198,7 @@
verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
.times(1)).onOpActiveChanged(eq(AppOpsManager.OPSTR_CAMERA),
eq(Process.myUid()), eq(getContext().getOpPackageName()),
- eq(getContext().getAttributionTag()), eq(virtualDeviceId.get()), eq(false),
+ eq(getContext().getAttributionTag()), eq(virtualDevice.getDeviceId()), eq(false),
eq(AppOpsManager.ATTRIBUTION_FLAGS_NONE),
eq(AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE));
verifyNoMoreInteractions(listener);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
index 90b131a..3dc375c 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
@@ -24,8 +24,6 @@
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED;
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_SUCCESS;
-import static com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR;
-
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
@@ -452,7 +450,6 @@
@Test
public void testRegisterAuthenticationStateListener_callsFingerprintService()
throws Exception {
- mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
setInternalAndTestBiometricPermissions(mContext, true /* hasPermission */);
mAuthService = new AuthService(mContext, mInjector);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java
index 74f8f08..d6eadf2 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/SensorOverlaysTest.java
@@ -16,8 +16,6 @@
package com.android.server.biometrics.sensors;
-import static com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR;
-
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -26,7 +24,6 @@
import static org.mockito.Mockito.when;
import android.hardware.biometrics.BiometricRequestConstants;
-import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
@@ -52,21 +49,18 @@
private static final long REQUEST_ID = 8;
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
-
@Mock private IUdfpsOverlayController mUdfpsOverlayController;
- @Mock private ISidefpsController mSidefpsController;
@Mock private AcquisitionClient<?> mAcquisitionClient;
@Before
public void setup() {
- mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
when(mAcquisitionClient.getRequestId()).thenReturn(REQUEST_ID);
when(mAcquisitionClient.hasRequestId()).thenReturn(true);
}
@Test
public void noopWhenBothNull() {
- final SensorOverlays useless = new SensorOverlays(null, null);
+ final SensorOverlays useless = new SensorOverlays(null);
useless.show(SENSOR_ID, 2, null);
useless.hide(SENSOR_ID);
}
@@ -74,34 +68,24 @@
@Test
public void testProvidesUdfps() {
final List<IUdfpsOverlayController> udfps = new ArrayList<>();
- SensorOverlays sensorOverlays = new SensorOverlays(null, mSidefpsController);
+ SensorOverlays sensorOverlays = new SensorOverlays(null);
sensorOverlays.ifUdfps(udfps::add);
assertThat(udfps).isEmpty();
- sensorOverlays = new SensorOverlays(mUdfpsOverlayController, mSidefpsController);
+ sensorOverlays = new SensorOverlays(mUdfpsOverlayController);
sensorOverlays.ifUdfps(udfps::add);
assertThat(udfps).containsExactly(mUdfpsOverlayController);
}
@Test
- public void testShow() throws Exception {
- testShow(mUdfpsOverlayController, mSidefpsController);
- }
-
- @Test
public void testShowUdfps() throws Exception {
- testShow(mUdfpsOverlayController, null);
+ testShow(mUdfpsOverlayController);
}
- @Test
- public void testShowSidefps() throws Exception {
- testShow(null, mSidefpsController);
- }
-
- private void testShow(IUdfpsOverlayController udfps, ISidefpsController sidefps)
+ private void testShow(IUdfpsOverlayController udfps)
throws Exception {
- final SensorOverlays sensorOverlays = new SensorOverlays(udfps, sidefps);
+ final SensorOverlays sensorOverlays = new SensorOverlays(udfps);
final int reason = BiometricRequestConstants.REASON_UNKNOWN;
sensorOverlays.show(SENSOR_ID, reason, mAcquisitionClient);
@@ -109,36 +93,20 @@
verify(mUdfpsOverlayController).showUdfpsOverlay(
eq(REQUEST_ID), eq(SENSOR_ID), eq(reason), any());
}
- if (sidefps != null) {
- verify(mSidefpsController).show(eq(SENSOR_ID), eq(reason));
- }
- }
-
- @Test
- public void testHide() throws Exception {
- testHide(mUdfpsOverlayController, mSidefpsController);
}
@Test
public void testHideUdfps() throws Exception {
- testHide(mUdfpsOverlayController, null);
+ testHide(mUdfpsOverlayController);
}
- @Test
- public void testHideSidefps() throws Exception {
- testHide(null, mSidefpsController);
- }
-
- private void testHide(IUdfpsOverlayController udfps, ISidefpsController sidefps)
+ private void testHide(IUdfpsOverlayController udfps)
throws Exception {
- final SensorOverlays sensorOverlays = new SensorOverlays(udfps, sidefps);
+ final SensorOverlays sensorOverlays = new SensorOverlays(udfps);
sensorOverlays.hide(SENSOR_ID);
if (udfps != null) {
verify(mUdfpsOverlayController).hideUdfpsOverlay(eq(SENSOR_ID));
}
- if (sidefps != null) {
- verify(mSidefpsController).hide(eq(SENSOR_ID));
- }
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
index a8e0c26..40de1b2 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
@@ -23,8 +23,6 @@
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
-import static com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR;
-
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -49,6 +47,7 @@
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.biometrics.common.OperationContext;
+import android.hardware.biometrics.common.OperationState;
import android.hardware.biometrics.events.AuthenticationAcquiredInfo;
import android.hardware.biometrics.events.AuthenticationErrorInfo;
import android.hardware.biometrics.events.AuthenticationFailedInfo;
@@ -61,7 +60,6 @@
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.IBinder;
import android.os.RemoteException;
@@ -82,6 +80,7 @@
import com.android.server.biometrics.log.OperationContextExt;
import com.android.server.biometrics.log.Probe;
import com.android.server.biometrics.sensors.AuthSessionCoordinator;
+import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.AuthenticationStateListeners;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
@@ -143,8 +142,6 @@
@Mock
private IUdfpsOverlayController mUdfpsOverlayController;
@Mock
- private ISidefpsController mSideFpsController;
- @Mock
private AuthenticationStateListeners mAuthenticationStateListeners;
@Mock
private FingerprintSensorPropertiesInternal mSensorProps;
@@ -189,7 +186,6 @@
@Before
public void setup() {
- mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
mContext.addMockSystemService(BiometricManager.class, mBiometricManager);
mContext.getOrCreateTestableResources().addOverride(
R.string.fingerprint_error_hw_not_available, "hw not available");
@@ -391,8 +387,8 @@
verify(mBiometricContext).subscribe(mOperationContextCaptor.capture(),
mStartHalConsumerCaptor.capture(), mContextInjector.capture(), any());
- mStartHalConsumerCaptor.getValue().accept(mOperationContextCaptor
- .getValue().toAidlContext());
+ final OperationContextExt operationContext = mOperationContextCaptor.getValue();
+ mStartHalConsumerCaptor.getValue().accept(operationContext.toAidlContext());
final ArgumentCaptor<OperationContext> captor =
ArgumentCaptor.forClass(OperationContext.class);
@@ -400,26 +396,30 @@
OperationContext opContext = captor.getValue();
- assertThat(opContext).isSameInstanceAs(
- mOperationContextCaptor.getValue().toAidlContext());
+ assertThat(opContext).isSameInstanceAs(operationContext.toAidlContext());
+ opContext.operationState = new OperationState();
+ opContext.operationState.setFingerprintOperationState(
+ new OperationState.FingerprintOperationState());
mContextInjector.getValue().accept(opContext);
verify(mHal).onContextChanged(same(opContext));
+ verify(mHal, times(2)).setIgnoreDisplayTouches(
+ opContext.operationState.getFingerprintOperationState().isHardwareIgnoringTouches);
client.stopHalOperation();
- verify(mBiometricContext).unsubscribe(same(mOperationContextCaptor.getValue()));
+ verify(mBiometricContext).unsubscribe(same(operationContext));
}
@Test
public void showHideOverlay_cancel() throws RemoteException {
- showHideOverlay(c -> c.cancel());
+ showHideOverlay(AuthenticationClient::cancel);
}
@Test
public void showHideOverlay_stop() throws RemoteException {
- showHideOverlay(c -> c.stopHalOperation());
+ showHideOverlay(FingerprintAuthenticationClient::stopHalOperation);
}
@Test
@@ -434,57 +434,13 @@
}
@Test
- public void showHideOverlay_lockoutPerm() throws RemoteException {
- showHideOverlay(c -> c.onLockoutPermanent());
- }
-
- private void showHideOverlay(Consumer<FingerprintAuthenticationClient> block)
+ public void showHideOverlay_lockoutPerm()
throws RemoteException {
- mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
- final FingerprintAuthenticationClient client = createClient();
-
- client.start(mCallback);
-
- verify(mUdfpsOverlayController).showUdfpsOverlay(eq(REQUEST_ID), anyInt(), anyInt(), any());
- verify(mSideFpsController).show(anyInt(), anyInt());
-
- block.accept(client);
-
- verify(mUdfpsOverlayController).hideUdfpsOverlay(anyInt());
- verify(mSideFpsController).hide(anyInt());
- verify(mHal, times(2)).setIgnoreDisplayTouches(false);
+ showHideOverlay(FingerprintAuthenticationClient::onLockoutPermanent);
}
- @Test
- public void showHideOverlay_cancel_sidefpsControllerRemovalRefactor() throws RemoteException {
- showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.cancel());
- }
-
- @Test
- public void showHideOverlay_stop_sidefpsControllerRemovalRefactor() throws RemoteException {
- showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.stopHalOperation());
- }
-
- @Test
- public void showHideOverlay_error_sidefpsControllerRemovalRefactor() throws RemoteException {
- showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.onError(0, 0));
- verify(mCallback).onClientFinished(any(), eq(false));
- }
-
- @Test
- public void showHideOverlay_lockout_sidefpsControllerRemovalRefactor() throws RemoteException {
- showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.onLockoutTimed(5000));
- }
-
- @Test
- public void showHideOverlay_lockoutPerm_sidefpsControllerRemovalRefactor()
- throws RemoteException {
- showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.onLockoutPermanent());
- }
-
- private void showHideOverlay_sidefpsControllerRemovalRefactor(
+ private void showHideOverlay(
Consumer<FingerprintAuthenticationClient> block) throws RemoteException {
- mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
final FingerprintAuthenticationClient client = createClient();
client.start(mCallback);
@@ -498,7 +454,6 @@
BiometricRequestConstants.REASON_AUTH_BP).build()
);
-
block.accept(client);
verify(mUdfpsOverlayController).hideUdfpsOverlay(anyInt());
@@ -552,7 +507,6 @@
@Test
public void testAuthenticationStateListeners_onError()
throws RemoteException {
- mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
final FingerprintAuthenticationClient client = createClient();
client.start(mCallback);
client.onError(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0);
@@ -578,7 +532,6 @@
@Test
public void testAuthenticationStateListeners_onLockoutPermanent()
throws RemoteException {
- mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
final FingerprintAuthenticationClient client = createClient();
client.start(mCallback);
client.onLockoutPermanent();
@@ -732,17 +685,12 @@
.setUserId(USER_ID)
.setSensorId(SENSOR_ID)
.build();
- return new FingerprintAuthenticationClient(mContext, () -> aidl, mToken,
- REQUEST_ID, listener, OP_ID,
- false /* restricted */, options, 4 /* cookie */,
- false /* requireConfirmation */,
- mBiometricLogger, mBiometricContext,
- true /* isStrongBiometric */,
- null /* taskStackListener */,
- mUdfpsOverlayController, mSideFpsController, mAuthenticationStateListeners,
- allowBackgroundAuthentication,
- mSensorProps, 0 /* biometricStrength */,
- lockoutTracker) {
+ return new FingerprintAuthenticationClient(mContext, () -> aidl, mToken, REQUEST_ID,
+ listener, OP_ID, false /* restricted */, options, 4 /* cookie */,
+ false /* requireConfirmation */, mBiometricLogger, mBiometricContext,
+ true /* isStrongBiometric */, null /* taskStackListener */, mUdfpsOverlayController,
+ mAuthenticationStateListeners, allowBackgroundAuthentication, mSensorProps,
+ 0 /* biometricStrength */, lockoutTracker) {
@Override
protected ActivityTaskManager getActivityTaskManager() {
return mActivityTaskManager;
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
index b26f8c8..5c6513d 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
@@ -20,8 +20,6 @@
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_TOO_FAST;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_TIMEOUT;
-import static com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR;
-
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -33,7 +31,6 @@
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.same;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -52,7 +49,6 @@
import android.hardware.fingerprint.FingerprintEnrollOptions;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.IBinder;
import android.os.RemoteException;
@@ -71,6 +67,7 @@
import com.android.server.biometrics.log.CallbackWithProbe;
import com.android.server.biometrics.log.OperationContextExt;
import com.android.server.biometrics.log.Probe;
+import com.android.server.biometrics.sensors.AcquisitionClient;
import com.android.server.biometrics.sensors.AuthenticationStateListeners;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
@@ -127,8 +124,6 @@
@Mock
private IUdfpsOverlayController mUdfpsOverlayController;
@Mock
- private ISidefpsController mSideFpsController;
- @Mock
private AuthenticationStateListeners mAuthenticationStateListeners;
@Mock
private FingerprintSensorPropertiesInternal mSensorProps;
@@ -287,12 +282,12 @@
@Test
public void showHideOverlay_cancel() throws RemoteException {
- showHideOverlay(c -> c.cancel());
+ showHideOverlay(AcquisitionClient::cancel);
}
@Test
public void showHideOverlay_stop() throws RemoteException {
- showHideOverlay(c -> c.stopHalOperation());
+ showHideOverlay(FingerprintEnrollClient::stopHalOperation);
}
@Test
@@ -303,45 +298,7 @@
@Test
public void showHideOverlay_result() throws RemoteException {
- showHideOverlay(c -> c.onEnrollResult(new Fingerprint("", 1, 1), 0));
- }
-
- private void showHideOverlay(Consumer<FingerprintEnrollClient> block)
- throws RemoteException {
- mSetFlagsRule.disableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
- final FingerprintEnrollClient client = createClient();
-
- client.start(mCallback);
-
- verify(mUdfpsOverlayController).showUdfpsOverlay(eq(REQUEST_ID), anyInt(), anyInt(), any());
- verify(mSideFpsController).show(anyInt(), anyInt());
-
- block.accept(client);
-
- verify(mUdfpsOverlayController).hideUdfpsOverlay(anyInt());
- verify(mSideFpsController).hide(anyInt());
- verify(mHal, times(2)).setIgnoreDisplayTouches(false);
- }
-
- @Test
- public void showHideOverlay_cancel_sidefpsControllerRemovalRefactor() throws RemoteException {
- showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.cancel());
- }
-
- @Test
- public void showHideOverlay_stop_sidefpsControllerRemovalRefactor() throws RemoteException {
- showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.stopHalOperation());
- }
-
- @Test
- public void showHideOverlay_error_sidefpsControllerRemovalRefactor() throws RemoteException {
- showHideOverlay_sidefpsControllerRemovalRefactor(c -> c.onError(0, 0));
- verify(mCallback).onClientFinished(any(), eq(false));
- }
-
- @Test
- public void showHideOverlay_result_sidefpsControllerRemovalRefactor() throws RemoteException {
- showHideOverlay_sidefpsControllerRemovalRefactor(
+ showHideOverlay(
c -> c.onEnrollResult(new Fingerprint("", 1, 1), 0));
}
@@ -355,9 +312,8 @@
eq(BiometricsProtoEnums.ENROLLMENT_SOURCE_SUW));
}
- private void showHideOverlay_sidefpsControllerRemovalRefactor(
+ private void showHideOverlay(
Consumer<FingerprintEnrollClient> block) throws RemoteException {
- mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
final FingerprintEnrollClient client = createClient();
client.start(mCallback);
@@ -414,7 +370,6 @@
@Test
public void testAuthenticationStateListeners_onError()
throws RemoteException {
- mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR);
final FingerprintEnrollClient client = createClient();
client.start(mCallback);
client.onError(FINGERPRINT_ERROR_TIMEOUT, 0);
@@ -449,7 +404,7 @@
mClientMonitorCallbackConverter, 0 /* userId */,
HAT, "owner", mBiometricUtils, 8 /* sensorId */,
mBiometricLogger, mBiometricContext, mSensorProps, mUdfpsOverlayController,
- mSideFpsController, mAuthenticationStateListeners, 6 /* maxTemplatesPerUser */,
+ mAuthenticationStateListeners, 6 /* maxTemplatesPerUser */,
FingerprintManager.ENROLL_ENROLL, (new FingerprintEnrollOptions.Builder())
.setEnrollReason(ENROLL_SOURCE).build()
);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapterTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapterTest.java
index 6c3bfe8..1db74b4 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapterTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/HidlToAidlSensorAdapterTest.java
@@ -217,7 +217,7 @@
mContext, mHidlToAidlSensorAdapter.getLazySession(), null /* token */,
1 /* requestId */, null /* listener */, USER_ID, HAT, TAG, mBiometricUtils,
SENSOR_ID, mLogger, mBiometricContext,
- mHidlToAidlSensorAdapter.getSensorProperties(), null, null,
+ mHidlToAidlSensorAdapter.getSensorProperties(), null,
mAuthenticationStateListeners, 5 /* maxTemplatesPerUser */, ENROLL_ENROLL,
(new FingerprintEnrollOptions.Builder()).build()));
mLooper.dispatchAll();
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index de3cfbf..855c658 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -30,8 +30,6 @@
import android.content.pm.IPackageManager;
import android.content.pm.PackageManagerInternal;
import android.database.ContentObserver;
-import android.hardware.usb.UsbManager;
-import android.media.IAudioService;
import android.net.IIpConnectivityMetrics;
import android.net.Uri;
import android.os.Bundle;
@@ -216,11 +214,6 @@
}
@Override
- IAudioService getIAudioService() {
- return services.iaudioService;
- }
-
- @Override
PersistentDataBlockManagerInternal getPersistentDataBlockManagerInternal() {
return services.persistentDataBlockManagerInternal;
}
@@ -244,11 +237,6 @@
}
@Override
- UsbManager getUsbManager() {
- return services.usbManager;
- }
-
- @Override
boolean storageManagerIsFileBasedEncryptionEnabled() {
return services.storageManager.isFileBasedEncryptionEnabled();
}
@@ -380,21 +368,11 @@
}
@Override
- void settingsSecurePutInt(String name, int value) {
- services.settings.settingsSecurePutInt(name, value);
- }
-
- @Override
void settingsGlobalPutInt(String name, int value) {
services.settings.settingsGlobalPutInt(name, value);
}
@Override
- void settingsSecurePutString(String name, String value) {
- services.settings.settingsSecurePutString(name, value);
- }
-
- @Override
void settingsGlobalPutString(String name, String value) {
services.settings.settingsGlobalPutString(name, value);
}
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index d6c5173..777f618 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -51,6 +51,7 @@
<uses-permission android:name="android.permission.MONITOR_INPUT"/>
<uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS"/>
<uses-permission android:name="android.permission.MANAGE_DEFAULT_APPLICATIONS"/>
+ <uses-permission android:name="android.permission.DUMP"/>
<!-- TODO: Remove largeHeap hack when memory leak is fixed (b/123984854) -->
<application android:debuggable="true"
diff --git a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
index 3c02eee..0ed02dd 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
@@ -21,6 +21,7 @@
import static android.view.KeyEvent.KEYCODE_BRIGHTNESS_DOWN;
import static android.view.KeyEvent.KEYCODE_C;
import static android.view.KeyEvent.KEYCODE_CTRL_LEFT;
+import static android.view.KeyEvent.KEYCODE_DEL;
import static android.view.KeyEvent.KEYCODE_E;
import static android.view.KeyEvent.KEYCODE_ENTER;
import static android.view.KeyEvent.KEYCODE_H;
@@ -42,16 +43,25 @@
import android.content.Intent;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.util.SparseArray;
import androidx.test.filters.SmallTest;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
@Presubmit
@SmallTest
public class ModifierShortcutTests extends ShortcutKeyTestBase {
+
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
private static final SparseArray<String> INTENT_SHORTCUTS = new SparseArray<>();
private static final SparseArray<String> ROLE_SHORTCUTS = new SparseArray<>();
static {
@@ -228,4 +238,25 @@
sendKeyCombination(new int[]{KEYCODE_SCREENSHOT}, 0);
mPhoneWindowManager.assertTakeScreenshotNotCalled();
}
+
+ /**
+ * META+CTRL+BACKSPACE for taking a bugreport when the flag is enabled.
+ */
+ @Test
+ @RequiresFlagsEnabled(com.android.server.flags.Flags.FLAG_NEW_BUGREPORT_KEYBOARD_SHORTCUT)
+ public void testTakeBugReport_flagEnabled() throws RemoteException {
+ sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_CTRL_LEFT, KEYCODE_DEL}, 0);
+ mPhoneWindowManager.assertTakeBugreport(true);
+ }
+
+ /**
+ * META+CTRL+BACKSPACE for taking a bugreport does nothing when the flag is disabledd.
+ */
+ @Test
+ @RequiresFlagsDisabled(com.android.server.flags.Flags.FLAG_NEW_BUGREPORT_KEYBOARD_SHORTCUT)
+ public void testTakeBugReport_flagDisabled() throws RemoteException {
+ sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_CTRL_LEFT, KEYCODE_DEL}, 0);
+ mPhoneWindowManager.assertTakeBugreport(false);
+ }
+
}
diff --git a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java b/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
index 60716cb..fd69217 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutLoggingTests.java
@@ -23,6 +23,9 @@
import static com.android.server.policy.PhoneWindowManager.SHORT_PRESS_SETTINGS_NOTIFICATION_PANEL;
import android.platform.test.annotations.Presubmit;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.view.KeyEvent;
import androidx.test.filters.MediumTest;
@@ -34,6 +37,7 @@
import junitparams.Parameters;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -42,6 +46,10 @@
@RunWith(JUnitParamsRunner.class)
public class ShortcutLoggingTests extends ShortcutKeyTestBase {
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule =
+ DeviceFlagsValueProvider.createCheckFlagsRule();
+
private static final int VENDOR_ID = 0x123;
private static final int PRODUCT_ID = 0x456;
private static final int DEVICE_BUS = 0x789;
@@ -153,8 +161,6 @@
new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DPAD_RIGHT},
KeyboardLogEvent.SPLIT_SCREEN_NAVIGATION, KeyEvent.KEYCODE_DPAD_RIGHT,
META_ON | CTRL_ON},
- {"Shift + Menu -> Trigger Bug Report", new int[]{SHIFT_KEY, KeyEvent.KEYCODE_MENU},
- KeyboardLogEvent.TRIGGER_BUG_REPORT, KeyEvent.KEYCODE_MENU, SHIFT_ON},
{"Meta + L -> Lock Homescreen", new int[]{META_KEY, KeyEvent.KEYCODE_L},
KeyboardLogEvent.LOCK_SCREEN, KeyEvent.KEYCODE_L, META_ON},
{"Meta + Ctrl + N -> Open Notes", new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_N},
@@ -353,4 +359,13 @@
expectedKey, expectedModifierState, DEVICE_BUS,
"Failed while executing " + testName);
}
+
+ @Test
+ @RequiresFlagsEnabled(com.android.server.flags.Flags.FLAG_NEW_BUGREPORT_KEYBOARD_SHORTCUT)
+ public void testBugreportShortcutPress() {
+ sendKeyCombination(new int[]{META_KEY, CTRL_KEY, KeyEvent.KEYCODE_DEL}, 0);
+ mPhoneWindowManager.assertShortcutLogged(VENDOR_ID, PRODUCT_ID,
+ KeyboardLogEvent.TRIGGER_BUG_REPORT, KeyEvent.KEYCODE_DEL, META_ON | CTRL_ON,
+ DEVICE_BUS, "Failed to log bugreport shortcut.");
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index eac9929..dd9d05a 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -88,6 +88,7 @@
import android.view.Display;
import android.view.InputDevice;
import android.view.KeyEvent;
+import android.view.accessibility.AccessibilityManager;
import android.view.autofill.AutofillManagerInternal;
import com.android.dx.mockito.inline.extended.StaticMockitoSession;
@@ -155,6 +156,7 @@
@Mock private AudioManagerInternal mAudioManagerInternal;
@Mock private SearchManager mSearchManager;
@Mock private RoleManager mRoleManager;
+ @Mock private AccessibilityManager mAccessibilityManager;
@Mock private Display mDisplay;
@Mock private DisplayRotation mDisplayRotation;
@@ -305,6 +307,9 @@
eq(SensorPrivacyManager.class));
doReturn(mSearchManager).when(mContext).getSystemService(eq(SearchManager.class));
doReturn(mRoleManager).when(mContext).getSystemService(eq(RoleManager.class));
+ doReturn(mAccessibilityManager).when(mContext).getSystemService(
+ eq(AccessibilityManager.class));
+ doReturn(false).when(mAccessibilityManager).isEnabled();
doReturn(false).when(mPackageManager).hasSystemFeature(any());
try {
doThrow(new PackageManager.NameNotFoundException("test")).when(mPackageManager)
@@ -602,7 +607,7 @@
}
void overrideEnableBugReportTrigger(boolean enable) {
- mPhoneWindowManager.mEnableShiftMenuBugReports = enable;
+ mPhoneWindowManager.mEnableBugReportKeyboardShortcut = enable;
}
void overrideStartActivity() {
@@ -746,12 +751,14 @@
eq(displayId), eq(mImeTargetWindowToken));
}
- void assertTakeBugreport() {
+ void assertTakeBugreport(boolean wasCalled) throws RemoteException {
mTestLooper.dispatchAll();
- ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
- verify(mContext).sendOrderedBroadcastAsUser(intentCaptor.capture(), any(), any(), any(),
- any(), anyInt(), any(), any());
- Assert.assertTrue(intentCaptor.getValue().getAction() == Intent.ACTION_BUG_REPORT);
+ if (wasCalled) {
+ verify(mActivityManagerService).requestInteractiveBugReport();
+ } else {
+ verify(mActivityManagerService, never()).requestInteractiveBugReport();
+ }
+
}
void assertTogglePanel() throws RemoteException {
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 400f9bb..4f94704 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -317,6 +317,70 @@
}
@Test
+ public void testEnterPipModeWhenResumed_autoEnterEnabled_returnTrue() {
+ final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
+ final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
+ PictureInPictureParams params = mock(PictureInPictureParams.class);
+ activity.pictureInPictureArgs = params;
+
+ doReturn(true).when(activity).isState(RESUMED);
+ doReturn(false).when(activity).inPinnedWindowingMode();
+ doReturn(true).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
+ doReturn(true).when(params).isAutoEnterEnabled();
+
+ assertTrue(mAtm.enterPictureInPictureMode(activity, params,
+ true /* fromClient */, true /* isAutoEnter */));
+ }
+
+ @Test
+ public void testEnterPipModeWhenResumed_autoEnterDisabled_returnTrue() {
+ final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
+ final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
+ PictureInPictureParams params = mock(PictureInPictureParams.class);
+ activity.pictureInPictureArgs = params;
+
+ doReturn(true).when(activity).isState(RESUMED);
+ doReturn(false).when(activity).inPinnedWindowingMode();
+ doReturn(true).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
+ doReturn(false).when(params).isAutoEnterEnabled();
+
+ assertTrue(mAtm.enterPictureInPictureMode(activity, params,
+ true /* fromClient */, false /* isAutoEnter */));
+ }
+
+ @Test
+ public void testEnterPipModeWhenPausing_autoEnterEnabled_returnFalse() {
+ final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
+ final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
+ PictureInPictureParams params = mock(PictureInPictureParams.class);
+ activity.pictureInPictureArgs = params;
+
+ doReturn(true).when(activity).isState(PAUSING);
+ doReturn(false).when(activity).inPinnedWindowingMode();
+ doReturn(true).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
+ doReturn(true).when(params).isAutoEnterEnabled();
+
+ assertFalse(mAtm.enterPictureInPictureMode(activity, params,
+ true /* fromClient */, true /* isAutoEnter */));
+ }
+
+ @Test
+ public void testEnterPipModeWhenPausing_autoEnterDisabled_returnTrue() {
+ final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
+ final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity();
+ PictureInPictureParams params = mock(PictureInPictureParams.class);
+ activity.pictureInPictureArgs = params;
+
+ doReturn(true).when(activity).isState(PAUSING);
+ doReturn(false).when(activity).inPinnedWindowingMode();
+ doReturn(true).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
+ doReturn(false).when(params).isAutoEnterEnabled();
+
+ assertTrue(mAtm.enterPictureInPictureMode(activity, params,
+ true /* fromClient */, false /* isAutoEnter */));
+ }
+
+ @Test
public void testResumeNextActivityOnCrashedAppDied() {
mSupervisor.beginDeferResume();
final ActivityRecord homeActivity = new ActivityBuilder(mAtm)
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java
index 6b614fa..27a4a2b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java
@@ -343,6 +343,20 @@
verify(mAtm).setLastResumedActivityUncheckLocked(any(), eq("test"));
}
+ @Test
+ public void testUpdateTopResumed_moveToFront() {
+ final ActivityRecord activity1 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ activity2.setState(ActivityRecord.State.RESUMED, "test");
+ assertEquals(activity2.app, mAtm.mTopApp);
+ activity1.getTask().moveToFront("test");
+ // If the device is not sleeping, the app should be only set with resumed state.
+ assertEquals(activity2.app, mAtm.mTopApp);
+ activity2.setState(ActivityRecord.State.PAUSED, "test");
+ activity1.setState(ActivityRecord.State.RESUMED, "test");
+ assertEquals(activity1.app, mAtm.mTopApp);
+ }
+
/**
* We need to launch home again after user unlocked for those displays that do not have
* encryption aware home app.
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index e14568d..e3a8542 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -38,6 +38,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
@@ -66,6 +67,7 @@
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
+import android.view.Display;
import android.view.DisplayAddress;
import android.view.IRotationWatcher;
import android.view.Surface;
@@ -217,6 +219,79 @@
}
@Test
+ public void testUserRotationSystemProperty_NonDefault_InternalDisplay() throws Exception {
+ mBuilder.setIsDefaultDisplay(false).build();
+ when(mMockDisplayContent.getDisplay().getType()).thenReturn(Display.TYPE_INTERNAL);
+ spyOn(mTarget);
+ when(mTarget.getDemoUserRotationOverride()).thenReturn(Surface.ROTATION_90);
+
+ mTarget.restoreSettings(WindowManagerPolicy.USER_ROTATION_FREE, Surface.ROTATION_270,
+ /*fixedToUserRotation=*/ 0);
+
+ assertEquals(Surface.ROTATION_270, mTarget.getUserRotation());
+ assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, mTarget.getUserRotationMode());
+ assertEquals(0, mTarget.getFixedToUserRotationMode());
+ }
+
+ @Test
+ public void testUserRotationSystemProperty_NonDefault_ExternalDisplay() throws Exception {
+ mBuilder.setIsDefaultDisplay(false).build();
+ when(mMockDisplayContent.getDisplay().getType()).thenReturn(Display.TYPE_EXTERNAL);
+ spyOn(mTarget);
+ when(mTarget.getDemoUserRotationOverride()).thenReturn(Surface.ROTATION_90);
+
+ mTarget.restoreSettings(WindowManagerPolicy.USER_ROTATION_FREE, Surface.ROTATION_270,
+ /*fixedToUserRotation=*/ 0);
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotationMode());
+ assertEquals(Surface.ROTATION_90, mTarget.getUserRotation());
+ assertEquals(0, mTarget.getFixedToUserRotationMode());
+ }
+
+ @Test
+ public void testUserRotationSystemProperty_NonDefault_OverlayDisplay() throws Exception {
+ mBuilder.setIsDefaultDisplay(false).build();
+ when(mMockDisplayContent.getDisplay().getType()).thenReturn(Display.TYPE_OVERLAY);
+ spyOn(mTarget);
+ when(mTarget.getDemoUserRotationOverride()).thenReturn(Surface.ROTATION_90);
+
+ mTarget.restoreSettings(WindowManagerPolicy.USER_ROTATION_FREE, Surface.ROTATION_270,
+ /*fixedToUserRotation=*/ 0);
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotationMode());
+ assertEquals(Surface.ROTATION_90, mTarget.getUserRotation());
+ assertEquals(0, mTarget.getFixedToUserRotationMode());
+ }
+
+ @Test
+ public void testUserRotationSystemProperty_NonDefault_VirtualDisplay() throws Exception {
+ mBuilder.setIsDefaultDisplay(false).build();
+ when(mMockDisplayContent.getDisplay().getType()).thenReturn(Display.TYPE_VIRTUAL);
+ final var packageName = "abc";
+ when(mMockDisplayContent.getDisplay().getOwnerPackageName()).thenReturn(packageName);
+ spyOn(mTarget);
+ when(mTarget.getDemoUserRotationOverride()).thenReturn(Surface.ROTATION_90);
+
+ // Without package name
+ when(mTarget.getDemoUserRotationPackage()).thenReturn("");
+ mTarget.restoreSettings(WindowManagerPolicy.USER_ROTATION_FREE, Surface.ROTATION_270,
+ /*fixedToUserRotation=*/ 0);
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, mTarget.getUserRotationMode());
+ assertEquals(Surface.ROTATION_270, mTarget.getUserRotation());
+ assertEquals(0, mTarget.getFixedToUserRotationMode());
+
+ // Use package name
+ when(mTarget.getDemoUserRotationPackage()).thenReturn(packageName);
+ mTarget.restoreSettings(WindowManagerPolicy.USER_ROTATION_FREE, Surface.ROTATION_270,
+ /*fixedToUserRotation=*/ 0);
+
+ assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotation());
+ assertEquals(Surface.ROTATION_90, mTarget.getUserRotationMode());
+ assertEquals(0, mTarget.getFixedToUserRotationMode());
+ }
+
+ @Test
public void testPersistUserRotation_UnlockRotation_DefaultDisplay() throws Exception {
mBuilder.build();
@@ -1450,6 +1525,7 @@
mMockContext = mock(Context.class);
mMockDisplayContent = mock(DisplayContent.class);
+ when(mMockDisplayContent.getDisplay()).thenReturn(mock(Display.class));
mMockDisplayContent.isDefaultDisplay = mIsDefaultDisplay;
when(mMockDisplayContent.calculateDisplayCutoutForRotation(anyInt()))
.thenReturn(NO_CUTOUT);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 000162a..ac1dc08 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -4484,6 +4484,21 @@
}
@Test
+ public void testPortraitAppInTabletop_notSplitScreen() {
+ final int dw = 2400;
+ setUpDisplaySizeWithApp(dw, 2000);
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+
+ final int initialWidth = mActivity.getBounds().width();
+
+ setFoldablePosture(true /* isHalfFolded */, true /* isTabletop */);
+
+ final int finalWidth = mActivity.getBounds().width();
+ assertEquals(initialWidth, finalWidth);
+ assertNotEquals(finalWidth, getExpectedSplitSize(dw));
+ }
+
+ @Test
public void testUpdateResolvedBoundsHorizontalPosition_bookModeEnabled() {
// Set up a display in landscape with a fixed-orientation PORTRAIT app
setUpDisplaySizeWithApp(2800, 1400);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index 69b5c37..43b424f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -1681,8 +1681,7 @@
WindowContainerToken wct = rootTask.mRemoteToken.toWindowContainerToken();
t.setWindowingMode(wct, WINDOWING_MODE_PINNED);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
- verify(mWm.mAtmService.mRootWindowContainer).resumeFocusedTasksTopActivitiesUnchecked(any(),
- any(), any(), anyBoolean());
+ verify(mWm.mAtmService.mRootWindowContainer).resumeFocusedTasksTopActivities();
clearInvocations(mWm.mAtmService.mRootWindowContainer);
// The token for the PIP root task may have changed when the task entered PIP mode, so do
@@ -1691,8 +1690,7 @@
record.getRootTask().mRemoteToken.toWindowContainerToken();
t.setWindowingMode(newToken, WINDOWING_MODE_FULLSCREEN);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
- verify(mWm.mAtmService.mRootWindowContainer).resumeFocusedTasksTopActivitiesUnchecked(any(),
- any(), any(), anyBoolean());
+ verify(mWm.mAtmService.mRootWindowContainer).resumeFocusedTasksTopActivities();
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index 400e4b6..059fed20 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -406,6 +406,7 @@
verify(tracker).onActivityResumedWhileVisible(mWpc);
assertTrue(tracker.hasResumedActivity(mWpc.mUid));
+ mAtm.mTopApp = null;
activity.makeFinishingLocked();
activity.setState(PAUSING, "test");
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 87bb0f0..b005715 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -954,6 +954,11 @@
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_MODEM_STATE_CONNECTED = 7;
/**
+ * The satellite modem is being powered on.
+ * @hide
+ */
+ public static final int SATELLITE_MODEM_STATE_ENABLING_SATELLITE = 8;
+ /**
* Satellite modem state is unknown. This generic modem state should be used only when the
* modem state cannot be mapped to other specific modem states.
*/
@@ -970,6 +975,7 @@
SATELLITE_MODEM_STATE_UNAVAILABLE,
SATELLITE_MODEM_STATE_NOT_CONNECTED,
SATELLITE_MODEM_STATE_CONNECTED,
+ SATELLITE_MODEM_STATE_ENABLING_SATELLITE,
SATELLITE_MODEM_STATE_UNKNOWN
})
@Retention(RetentionPolicy.SOURCE)
diff --git a/tests/FlickerTests/test-apps/app-helpers/OWNERS b/tests/FlickerTests/test-apps/app-helpers/OWNERS
new file mode 100644
index 0000000..ab62532
--- /dev/null
+++ b/tests/FlickerTests/test-apps/app-helpers/OWNERS
@@ -0,0 +1,2 @@
+uysalorhan@google.com
+pragyabajoria@google.com
\ No newline at end of file
diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
new file mode 100644
index 0000000..461dfec
--- /dev/null
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2024 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.wm.flicker.helpers
+
+import android.tools.device.apphelpers.IStandardAppHelper
+import android.tools.helpers.SYSTEMUI_PACKAGE
+import android.tools.traces.parsers.WindowManagerStateHelper
+import android.tools.traces.wm.WindowingMode
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.BySelector
+import androidx.test.uiautomator.UiDevice
+import androidx.test.uiautomator.UiObject2
+import androidx.test.uiautomator.Until
+
+/**
+ * Wrapper class around App helper classes. This class adds functionality to the apps that the
+ * desktop apps would have.
+ */
+open class DesktopModeAppHelper(private val innerHelper: IStandardAppHelper) :
+ IStandardAppHelper by innerHelper {
+ private val TIMEOUT_MS = 3_000L
+ private val CAPTION = "desktop_mode_caption"
+ private val CAPTION_HANDLE = "caption_handle"
+ private val MAXIMIZE_BUTTON = "maximize_window"
+ private val MAXIMIZE_BUTTON_VIEW = "maximize_button_view"
+ private val CLOSE_BUTTON = "close_window"
+
+ private val caption: BySelector
+ get() = By.res(SYSTEMUI_PACKAGE, CAPTION)
+
+ /** Wait for an app moved to desktop to finish its transition. */
+ private fun waitForAppToMoveToDesktop(wmHelper: WindowManagerStateHelper) {
+ wmHelper
+ .StateSyncBuilder()
+ .withWindowSurfaceAppeared(innerHelper)
+ .withFreeformApp(innerHelper)
+ .withAppTransitionIdle()
+ .waitForAndVerify()
+ }
+
+ /** Move an app to Desktop by dragging the app handle at the top. */
+ fun enterDesktopWithDrag(
+ wmHelper: WindowManagerStateHelper,
+ device: UiDevice,
+ ) {
+ innerHelper.launchViaIntent(wmHelper)
+ dragToDesktop(wmHelper, device)
+ waitForAppToMoveToDesktop(wmHelper)
+ }
+
+ private fun dragToDesktop(wmHelper: WindowManagerStateHelper, device: UiDevice) {
+ val windowRect = wmHelper.getWindowRegion(innerHelper).bounds
+ val startX = windowRect.centerX()
+
+ // Start dragging a little under the top to prevent dragging the notification shade.
+ val startY = 10
+
+ val displayRect =
+ wmHelper.currentState.wmState.getDefaultDisplay()?.displayRect
+ ?: throw IllegalStateException("Default display is null")
+
+ // The position we want to drag to
+ val endY = displayRect.centerY() / 2
+
+ // drag the window to move to desktop
+ device.drag(startX, startY, startX, endY, 100)
+ }
+
+ /** Click maximise button on the app header for the given app. */
+ fun maximiseDesktopApp(wmHelper: WindowManagerStateHelper, device: UiDevice) {
+ val caption = getCaptionForTheApp(wmHelper, device)
+ val maximizeButton =
+ caption
+ ?.children
+ ?.find { it.resourceName.endsWith(MAXIMIZE_BUTTON_VIEW) }
+ ?.children
+ ?.get(0)
+ maximizeButton?.click()
+ wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
+ }
+ /** Click close button on the app header for the given app. */
+ fun closeDesktopApp(wmHelper: WindowManagerStateHelper, device: UiDevice) {
+ val caption = getCaptionForTheApp(wmHelper, device)
+ val closeButton = caption?.children?.find { it.resourceName.endsWith(CLOSE_BUTTON) }
+ closeButton?.click()
+ wmHelper
+ .StateSyncBuilder()
+ .withAppTransitionIdle()
+ .withWindowSurfaceDisappeared(innerHelper)
+ .waitForAndVerify()
+ }
+
+ private fun getCaptionForTheApp(
+ wmHelper: WindowManagerStateHelper,
+ device: UiDevice
+ ): UiObject2? {
+ if (
+ wmHelper.getWindow(innerHelper)?.windowingMode !=
+ WindowingMode.WINDOWING_MODE_FREEFORM.value
+ )
+ error("expected a freeform window with caption but window is not in freeform mode")
+ val captions =
+ device.wait(Until.findObjects(caption), TIMEOUT_MS)
+ ?: error("Unable to find view $caption\n")
+
+ return captions.find {
+ wmHelper.getWindowRegion(innerHelper).bounds.contains(it.visibleBounds)
+ }
+ }
+}